mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-08-07 02:32:27 +02:00
Initial devel branch import from bash-3.0-alpha
This commit is contained in:
+57
-11
@@ -181,10 +181,14 @@ mbskipname (pat, dname)
|
||||
|
||||
n = strlen(pat);
|
||||
pat_bak = (char *) alloca (n + 1);
|
||||
if (pat_bak == 0)
|
||||
return 0;
|
||||
memcpy (pat_bak, pat, n + 1);
|
||||
|
||||
n = strlen(dname);
|
||||
dn_bak = (char *) alloca (n + 1);
|
||||
if (dn_bak == 0)
|
||||
return 0;
|
||||
memcpy (dn_bak, dname, n + 1);
|
||||
|
||||
memset(&pat_ps, '\0', sizeof(mbstate_t));
|
||||
@@ -198,6 +202,9 @@ mbskipname (pat, dname)
|
||||
pat_wc = (wchar_t *) alloca ((pat_n + 1) * sizeof(wchar_t));
|
||||
dn_wc = (wchar_t *) alloca ((dn_n + 1) * sizeof(wchar_t));
|
||||
|
||||
if (pat_wc == 0 || dn_wc == 0)
|
||||
return 0;
|
||||
|
||||
(void) xmbsrtowcs (pat_wc, (const char **)&pat_bak, pat_n + 1, &pat_ps);
|
||||
(void) xmbsrtowcs (dn_wc, (const char **)&dn_bak, dn_n + 1, &dn_ps);
|
||||
|
||||
@@ -255,6 +262,8 @@ wdequote_pathname (pathname)
|
||||
|
||||
len = strlen (pathname);
|
||||
pathname_bak = (char *) alloca (len + 1);
|
||||
if (pathname_bak == 0)
|
||||
return;
|
||||
memcpy (pathname_bak, pathname , len + 1);
|
||||
|
||||
/* Convert the strings into wide characters. */
|
||||
@@ -264,7 +273,10 @@ wdequote_pathname (pathname)
|
||||
/* Something wrong. */
|
||||
return;
|
||||
|
||||
wpathname = (wchar_t *) alloca ((n + 1) * sizeof (wchar_t));
|
||||
wpathname = (wchar_t *)alloca ((n + 1) * sizeof (wchar_t));
|
||||
if (wpathname == 0)
|
||||
return;
|
||||
|
||||
(void) xmbsrtowcs (wpathname, (const char **)&pathname_bak, n + 1, &ps);
|
||||
|
||||
for (i = j = 0; wpathname && wpathname[i]; )
|
||||
@@ -373,6 +385,9 @@ glob_vector (pat, dir, flags)
|
||||
return ((char **) &glob_error_return);
|
||||
|
||||
nextlink = (struct globval *)alloca (sizeof (struct globval));
|
||||
if (nextlink == NULL)
|
||||
return ((char **) NULL);
|
||||
|
||||
nextlink->next = (struct globval *)0;
|
||||
nextname = (char *) malloc (1);
|
||||
if (nextname == 0)
|
||||
@@ -418,10 +433,15 @@ glob_vector (pat, dir, flags)
|
||||
{
|
||||
free (nextname);
|
||||
nextlink = (struct globval *)alloca (sizeof (struct globval));
|
||||
nextlink->next = (struct globval *)0;
|
||||
lastlink = nextlink;
|
||||
nextlink->name = npat;
|
||||
count = 1;
|
||||
if (nextlink)
|
||||
{
|
||||
nextlink->next = (struct globval *)0;
|
||||
lastlink = nextlink;
|
||||
nextlink->name = npat;
|
||||
count = 1;
|
||||
}
|
||||
else
|
||||
lose = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -490,14 +510,14 @@ glob_vector (pat, dir, flags)
|
||||
|
||||
if (strmatch (pat, dp->d_name, mflags) != FNM_NOMATCH)
|
||||
{
|
||||
nextlink = (struct globval *) alloca (sizeof (struct globval));
|
||||
nextlink->next = lastlink;
|
||||
nextname = (char *) malloc (D_NAMLEN (dp) + 1);
|
||||
if (nextname == NULL)
|
||||
nextlink = (struct globval *) alloca (sizeof (struct globval));
|
||||
if (nextlink == 0 || nextname == 0)
|
||||
{
|
||||
lose = 1;
|
||||
break;
|
||||
}
|
||||
nextlink->next = lastlink;
|
||||
lastlink = nextlink;
|
||||
nextlink->name = nextname;
|
||||
bcopy (dp->d_name, nextname, D_NAMLEN (dp) + 1);
|
||||
@@ -631,6 +651,7 @@ glob_filename (pathname, flags)
|
||||
unsigned int result_size;
|
||||
char *directory_name, *filename;
|
||||
unsigned int directory_len;
|
||||
int free_dirname; /* flag */
|
||||
|
||||
result = (char **) malloc (sizeof (char *));
|
||||
result_size = 1;
|
||||
@@ -639,6 +660,8 @@ glob_filename (pathname, flags)
|
||||
|
||||
result[0] = NULL;
|
||||
|
||||
directory_name = NULL;
|
||||
|
||||
/* Find the filename. */
|
||||
filename = strrchr (pathname, '/');
|
||||
if (filename == NULL)
|
||||
@@ -646,15 +669,20 @@ glob_filename (pathname, flags)
|
||||
filename = pathname;
|
||||
directory_name = "";
|
||||
directory_len = 0;
|
||||
free_dirname = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
directory_len = (filename - pathname) + 1;
|
||||
directory_name = (char *) alloca (directory_len + 1);
|
||||
directory_name = (char *) malloc (directory_len + 1);
|
||||
|
||||
if (directory_name == 0) /* allocation failed? */
|
||||
return (NULL);
|
||||
|
||||
bcopy (pathname, directory_name, directory_len);
|
||||
directory_name[directory_len] = '\0';
|
||||
++filename;
|
||||
free_dirname = 1;
|
||||
}
|
||||
|
||||
/* If directory_name contains globbing characters, then we
|
||||
@@ -669,6 +697,12 @@ glob_filename (pathname, flags)
|
||||
|
||||
directories = glob_filename (directory_name, flags & ~GX_MARKDIRS);
|
||||
|
||||
if (free_dirname)
|
||||
{
|
||||
free (directory_name);
|
||||
directory_name = NULL;
|
||||
}
|
||||
|
||||
if (directories == NULL)
|
||||
goto memory_error;
|
||||
else if (directories == (char **)&glob_error_return)
|
||||
@@ -746,6 +780,8 @@ glob_filename (pathname, flags)
|
||||
if (result[0] == NULL)
|
||||
goto memory_error;
|
||||
bcopy (directory_name, result[0], directory_len + 1);
|
||||
if (free_dirname)
|
||||
free (directory_name);
|
||||
result[1] = NULL;
|
||||
return (result);
|
||||
}
|
||||
@@ -770,9 +806,16 @@ glob_filename (pathname, flags)
|
||||
flags & ~GX_MARKDIRS);
|
||||
|
||||
if (temp_results == NULL || temp_results == (char **)&glob_error_return)
|
||||
return (temp_results);
|
||||
{
|
||||
if (free_dirname)
|
||||
free (directory_name);
|
||||
return (temp_results);
|
||||
}
|
||||
|
||||
return (glob_dir_to_array (directory_name, temp_results, flags));
|
||||
result = glob_dir_to_array (directory_name, temp_results, flags);
|
||||
if (free_dirname)
|
||||
free (directory_name);
|
||||
return (result);
|
||||
}
|
||||
|
||||
/* We get to memory_error if the program has run out of memory, or
|
||||
@@ -786,6 +829,9 @@ glob_filename (pathname, flags)
|
||||
free ((char *) result);
|
||||
}
|
||||
|
||||
if (free_dirname && directory_name)
|
||||
free (directory_name);
|
||||
|
||||
QUIT;
|
||||
|
||||
return (NULL);
|
||||
|
||||
@@ -134,6 +134,19 @@ fprintf(stderr, "gmatch: pattern = %s; pe = %s\n", pattern, pe);
|
||||
if ((flags & FNM_PATHNAME) && sc == L('/'))
|
||||
/* A slash does not match a wildcard under FNM_PATHNAME. */
|
||||
return FNM_NOMATCH;
|
||||
#ifdef EXTENDED_GLOB
|
||||
else if ((flags & FNM_EXTMATCH) && c == L('?') && *p == L('(')) /* ) */
|
||||
{
|
||||
CHAR *newn;
|
||||
for (newn = n; newn < se; ++newn)
|
||||
{
|
||||
if (EXTMATCH (c, newn, se, p, pe, flags) == 0)
|
||||
return (0);
|
||||
}
|
||||
/* We didn't match. If we have a `?(...)', that's failure. */
|
||||
return FNM_NOMATCH;
|
||||
}
|
||||
#endif
|
||||
else if (c == L('?'))
|
||||
{
|
||||
if (sc == L('\0'))
|
||||
|
||||
+5
-1
@@ -236,7 +236,7 @@ static unsigned long binsizes[NBUCKETS] = {
|
||||
8192UL, 16384UL, 32768UL, 65536UL, 131072UL, 262144UL, 524288UL,
|
||||
1048576UL, 2097152UL, 4194304UL, 8388608UL, 16777216UL, 33554432UL,
|
||||
67108864UL, 134217728UL, 268435456UL, 536870912UL, 1073741824UL,
|
||||
2147483648UL, 4294967296UL-1
|
||||
2147483648UL, 4294967295UL
|
||||
};
|
||||
|
||||
/* binsizes[x] == (1 << ((x) + 3)) */
|
||||
@@ -291,6 +291,9 @@ extern void mtrace_free __P((PTR_T, int, const char *, int));
|
||||
#if !defined (botch)
|
||||
static void
|
||||
botch (s, file, line)
|
||||
const char *s;
|
||||
const char *file;
|
||||
int line;
|
||||
{
|
||||
fprintf (stderr, "malloc: failed assertion: %s\n", s);
|
||||
(void)fflush (stderr);
|
||||
@@ -879,6 +882,7 @@ internal_free (mem, file, line, flags)
|
||||
busy[nunits] = 0;
|
||||
|
||||
free_return:
|
||||
; /* Empty statement in case this is the end of the function */
|
||||
|
||||
#ifdef MALLOC_STATS
|
||||
_mstats.nmalloc[nunits]--;
|
||||
|
||||
@@ -345,7 +345,7 @@ search.o: search.c
|
||||
shell.o: shell.c
|
||||
signals.o: signals.c
|
||||
terminal.o: terminal.c
|
||||
text.o: terminal.c
|
||||
text.o: text.c
|
||||
tilde.o: tilde.c
|
||||
undo.o: undo.c
|
||||
util.o: util.c
|
||||
|
||||
+94
-26
@@ -148,6 +148,34 @@ rl_bind_key_in_map (key, function, map)
|
||||
return (result);
|
||||
}
|
||||
|
||||
/* Bind key sequence KEYSEQ to DEFAULT_FUNC if KEYSEQ is unbound. Right
|
||||
now, this is always used to attempt to bind the arrow keys, hence the
|
||||
check for rl_vi_movement_mode. */
|
||||
int
|
||||
rl_bind_key_if_unbound_in_map (key, default_func, kmap)
|
||||
int key;
|
||||
rl_command_func_t *default_func;
|
||||
Keymap kmap;
|
||||
{
|
||||
char keyseq[2];
|
||||
|
||||
keyseq[0] = (unsigned char)key;
|
||||
keyseq[1] = '\0';
|
||||
return (rl_bind_keyseq_if_unbound_in_map (keyseq, default_func, kmap));
|
||||
}
|
||||
|
||||
int
|
||||
rl_bind_key_if_unbound (key, default_func)
|
||||
int key;
|
||||
rl_command_func_t *default_func;
|
||||
{
|
||||
char keyseq[2];
|
||||
|
||||
keyseq[0] = (unsigned char)key;
|
||||
keyseq[1] = '\0';
|
||||
return (rl_bind_keyseq_if_unbound_in_map (keyseq, default_func, _rl_keymap));
|
||||
}
|
||||
|
||||
/* Make KEY do nothing in the currently selected keymap.
|
||||
Returns non-zero in case of error. */
|
||||
int
|
||||
@@ -199,10 +227,31 @@ rl_unbind_command_in_map (command, map)
|
||||
return (rl_unbind_function_in_map (func, map));
|
||||
}
|
||||
|
||||
/* Bind the key sequence represented by the string KEYSEQ to
|
||||
FUNCTION, starting in the current keymap. This makes new
|
||||
keymaps as necessary. */
|
||||
int
|
||||
rl_bind_keyseq (keyseq, function)
|
||||
const char *keyseq;
|
||||
rl_command_func_t *function;
|
||||
{
|
||||
return (rl_generic_bind (ISFUNC, keyseq, (char *)function, _rl_keymap));
|
||||
}
|
||||
|
||||
/* Bind the key sequence represented by the string KEYSEQ to
|
||||
FUNCTION. This makes new keymaps as necessary. The initial
|
||||
place to do bindings is in MAP. */
|
||||
int
|
||||
rl_bind_keyseq_in_map (keyseq, function, map)
|
||||
const char *keyseq;
|
||||
rl_command_func_t *function;
|
||||
Keymap map;
|
||||
{
|
||||
return (rl_generic_bind (ISFUNC, keyseq, (char *)function, map));
|
||||
}
|
||||
|
||||
/* Backwards compatibility; equivalent to rl_bind_keyseq_in_map() */
|
||||
int
|
||||
rl_set_key (keyseq, function, map)
|
||||
const char *keyseq;
|
||||
rl_command_func_t *function;
|
||||
@@ -211,6 +260,40 @@ rl_set_key (keyseq, function, map)
|
||||
return (rl_generic_bind (ISFUNC, keyseq, (char *)function, map));
|
||||
}
|
||||
|
||||
/* Bind key sequence KEYSEQ to DEFAULT_FUNC if KEYSEQ is unbound. Right
|
||||
now, this is always used to attempt to bind the arrow keys, hence the
|
||||
check for rl_vi_movement_mode. */
|
||||
int
|
||||
rl_bind_keyseq_if_unbound_in_map (keyseq, default_func, kmap)
|
||||
const char *keyseq;
|
||||
rl_command_func_t *default_func;
|
||||
Keymap kmap;
|
||||
{
|
||||
rl_command_func_t *func;
|
||||
|
||||
if (keyseq)
|
||||
{
|
||||
func = rl_function_of_keyseq (keyseq, kmap, (int *)NULL);
|
||||
#if defined (VI_MODE)
|
||||
if (!func || func == rl_do_lowercase_version || func == rl_vi_movement_mode)
|
||||
#else
|
||||
if (!func || func == rl_do_lowercase_version)
|
||||
#endif
|
||||
return (rl_bind_keyseq_in_map (keyseq, default_func, kmap));
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
rl_bind_keyseq_if_unbound (keyseq, default_func)
|
||||
const char *keyseq;
|
||||
rl_command_func_t *default_func;
|
||||
{
|
||||
return (rl_bind_keyseq_if_unbound_in_map (keyseq, default_func, _rl_keymap));
|
||||
}
|
||||
|
||||
/* Bind the key sequence represented by the string KEYSEQ to
|
||||
the string of characters MACRO. This makes new keymaps as
|
||||
necessary. The initial place to do bindings is in MAP. */
|
||||
@@ -311,7 +394,7 @@ rl_generic_bind (type, keyseq, data, map)
|
||||
mapped to something, `abc' to be mapped to something else,
|
||||
and the function bound to `a' to be executed when the user
|
||||
types `abx', leaving `bx' in the input queue. */
|
||||
if (k.function /* && k.type == ISFUNC */)
|
||||
if (k.function && ((k.type == ISFUNC && k.function != rl_do_lowercase_version) || k.type == ISMACR))
|
||||
{
|
||||
map[ANYOTHERKEY] = k;
|
||||
k.function = 0;
|
||||
@@ -912,9 +995,15 @@ parser_else (args)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Check the previous (n - 1) levels of the stack to make sure that
|
||||
we haven't previously turned off parsing. */
|
||||
for (i = 0; i < if_stack_depth - 1; i++)
|
||||
#else
|
||||
/* Check the previous (n) levels of the stack to make sure that
|
||||
we haven't previously turned off parsing. */
|
||||
for (i = 0; i < if_stack_depth; i++)
|
||||
#endif
|
||||
if (if_stack[i] == 1)
|
||||
return 0;
|
||||
|
||||
@@ -1161,7 +1250,7 @@ rl_parse_and_bind (string)
|
||||
}
|
||||
|
||||
/* If this is a new-style key-binding, then do the binding with
|
||||
rl_set_key (). Otherwise, let the older code deal with it. */
|
||||
rl_bind_keyseq (). Otherwise, let the older code deal with it. */
|
||||
if (*string == '"')
|
||||
{
|
||||
char *seq;
|
||||
@@ -1200,7 +1289,7 @@ rl_parse_and_bind (string)
|
||||
rl_macro_bind (seq, &funname[1], _rl_keymap);
|
||||
}
|
||||
else
|
||||
rl_set_key (seq, rl_named_function (funname), _rl_keymap);
|
||||
rl_bind_keyseq (seq, rl_named_function (funname));
|
||||
|
||||
free (seq);
|
||||
return 0;
|
||||
@@ -1281,6 +1370,7 @@ static struct {
|
||||
{ "prefer-visible-bell", &_rl_prefer_visible_bell, V_SPECIAL },
|
||||
{ "print-completions-horizontally", &_rl_print_completions_horizontally, 0 },
|
||||
{ "show-all-if-ambiguous", &_rl_complete_show_all, 0 },
|
||||
{ "show-all-if-unmodified", &_rl_complete_show_unmodified, 0 },
|
||||
#if defined (VISIBLE_STATS)
|
||||
{ "visible-stats", &rl_visible_stats, 0 },
|
||||
#endif /* VISIBLE_STATS */
|
||||
@@ -1650,7 +1740,7 @@ rl_get_keymap_name_from_edit_mode ()
|
||||
/* Each of the following functions produces information about the
|
||||
state of keybindings and functions known to Readline. The info
|
||||
is always printed to rl_outstream, and in such a way that it can
|
||||
be read back in (i.e., passed to rl_parse_and_bind (). */
|
||||
be read back in (i.e., passed to rl_parse_and_bind ()). */
|
||||
|
||||
/* Print the names of functions known to Readline. */
|
||||
void
|
||||
@@ -2112,28 +2202,6 @@ rl_dump_variables (count, key)
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Bind key sequence KEYSEQ to DEFAULT_FUNC if KEYSEQ is unbound. Right
|
||||
now, this is always used to attempt to bind the arrow keys, hence the
|
||||
check for rl_vi_movement_mode. */
|
||||
void
|
||||
_rl_bind_if_unbound (keyseq, default_func)
|
||||
const char *keyseq;
|
||||
rl_command_func_t *default_func;
|
||||
{
|
||||
rl_command_func_t *func;
|
||||
|
||||
if (keyseq)
|
||||
{
|
||||
func = rl_function_of_keyseq (keyseq, _rl_keymap, (int *)NULL);
|
||||
#if defined (VI_MODE)
|
||||
if (!func || func == rl_do_lowercase_version || func == rl_vi_movement_mode)
|
||||
#else
|
||||
if (!func || func == rl_do_lowercase_version)
|
||||
#endif
|
||||
rl_set_key (keyseq, default_func, _rl_keymap);
|
||||
}
|
||||
}
|
||||
|
||||
/* Return non-zero if any members of ARRAY are a substring in STRING. */
|
||||
static int
|
||||
substring_member_of_array (string, array)
|
||||
|
||||
@@ -131,7 +131,7 @@ rl_callback_read_char ()
|
||||
if (in_handler == 0 && rl_linefunc)
|
||||
_rl_callback_newline ();
|
||||
}
|
||||
if (rl_pending_input)
|
||||
if (rl_pending_input || _rl_pushed_input_available ())
|
||||
eof = readline_internal_char ();
|
||||
else
|
||||
break;
|
||||
|
||||
@@ -77,7 +77,11 @@
|
||||
# define isxdigit(c) (isdigit((c)) || ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F'))
|
||||
#endif
|
||||
|
||||
#define NON_NEGATIVE(c) ((unsigned char)(c) == (c))
|
||||
#if defined (CTYPE_NON_ASCII)
|
||||
# define NON_NEGATIVE(c) 1
|
||||
#else
|
||||
# define NON_NEGATIVE(c) ((unsigned char)(c) == (c))
|
||||
#endif
|
||||
|
||||
/* Some systems define these; we want our definitions. */
|
||||
#undef ISPRINT
|
||||
|
||||
+152
-38
@@ -28,7 +28,7 @@
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#if defined (HAVE_SYS_FILE_H)
|
||||
#include <sys/file.h>
|
||||
# include <sys/file.h>
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
@@ -105,6 +105,8 @@ static void set_completion_defaults PARAMS((int));
|
||||
static int get_y_or_n PARAMS((int));
|
||||
static int _rl_internal_pager PARAMS((int));
|
||||
static char *printable_part PARAMS((char *));
|
||||
static int fnwidth PARAMS((const char *));
|
||||
static int fnprint PARAMS((const char *));
|
||||
static int print_filename PARAMS((char *, char *));
|
||||
|
||||
static char **gen_completion_matches PARAMS((char *, int, int, rl_compentry_func_t *, int, int));
|
||||
@@ -130,6 +132,10 @@ static char *make_quoted_replacement PARAMS((char *, int, char *));
|
||||
/* If non-zero, non-unique completions always show the list of matches. */
|
||||
int _rl_complete_show_all = 0;
|
||||
|
||||
/* If non-zero, non-unique completions show the list of matches, unless it
|
||||
is not possible to do partial completion and modify the line. */
|
||||
int _rl_complete_show_unmodified = 0;
|
||||
|
||||
/* If non-zero, completed directory names have a slash appended. */
|
||||
int _rl_complete_mark_directories = 1;
|
||||
|
||||
@@ -214,7 +220,7 @@ const char *rl_basic_quote_characters = "\"'";
|
||||
/* The list of characters that signal a break between words for
|
||||
rl_complete_internal. The default list is the contents of
|
||||
rl_basic_word_break_characters. */
|
||||
const char *rl_completer_word_break_characters = (const char *)NULL;
|
||||
/*const*/ char *rl_completer_word_break_characters = (/*const*/ char *)NULL;
|
||||
|
||||
/* List of characters which can be used to quote a substring of the line.
|
||||
Completion occurs on the entire substring, and within the substring
|
||||
@@ -320,6 +326,8 @@ rl_complete (ignore, invoking_key)
|
||||
return (rl_complete_internal ('?'));
|
||||
else if (_rl_complete_show_all)
|
||||
return (rl_complete_internal ('!'));
|
||||
else if (_rl_complete_show_unmodified)
|
||||
return (rl_complete_internal ('@'));
|
||||
else
|
||||
return (rl_complete_internal (TAB));
|
||||
}
|
||||
@@ -352,6 +360,8 @@ rl_completion_mode (cfunc)
|
||||
return '?';
|
||||
else if (_rl_complete_show_all)
|
||||
return '!';
|
||||
else if (_rl_complete_show_unmodified)
|
||||
return '@';
|
||||
else
|
||||
return TAB;
|
||||
}
|
||||
@@ -520,52 +530,139 @@ printable_part (pathname)
|
||||
return ++temp;
|
||||
}
|
||||
|
||||
/* Compute width of STRING when displayed on screen by print_filename */
|
||||
static int
|
||||
fnwidth (string)
|
||||
const char *string;
|
||||
{
|
||||
int width, pos;
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
mbstate_t ps;
|
||||
int left, w;
|
||||
size_t clen;
|
||||
wchar_t wc;
|
||||
|
||||
left = strlen (string) + 1;
|
||||
memset (&ps, 0, sizeof (mbstate_t));
|
||||
#endif
|
||||
|
||||
width = pos = 0;
|
||||
while (string[pos])
|
||||
{
|
||||
if (CTRL_CHAR (*string) || *string == RUBOUT)
|
||||
{
|
||||
width += 2;
|
||||
pos++;
|
||||
}
|
||||
else
|
||||
{
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
clen = mbrtowc (&wc, string + pos, left - pos, &ps);
|
||||
if (MB_INVALIDCH (clen))
|
||||
{
|
||||
width++;
|
||||
pos++;
|
||||
memset (&ps, 0, sizeof (mbstate_t));
|
||||
}
|
||||
else if (MB_NULLWCH (clen))
|
||||
break;
|
||||
else
|
||||
{
|
||||
pos += clen;
|
||||
w = wcwidth (wc);
|
||||
width += (w >= 0) ? w : 1;
|
||||
}
|
||||
#else
|
||||
width++;
|
||||
pos++;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return width;
|
||||
}
|
||||
|
||||
static int
|
||||
fnprint (to_print)
|
||||
const char *to_print;
|
||||
{
|
||||
int printed_len;
|
||||
const char *s;
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
mbstate_t ps;
|
||||
const char *end;
|
||||
size_t tlen;
|
||||
|
||||
end = to_print + strlen (to_print) + 1;
|
||||
memset (&ps, 0, sizeof (mbstate_t));
|
||||
#endif
|
||||
|
||||
printed_len = 0;
|
||||
s = to_print;
|
||||
while (*s)
|
||||
{
|
||||
if (CTRL_CHAR (*s))
|
||||
{
|
||||
putc ('^', rl_outstream);
|
||||
putc (UNCTRL (*s), rl_outstream);
|
||||
printed_len += 2;
|
||||
s++;
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
memset (&ps, 0, sizeof (mbstate_t));
|
||||
#endif
|
||||
}
|
||||
else if (*s == RUBOUT)
|
||||
{
|
||||
putc ('^', rl_outstream);
|
||||
putc ('?', rl_outstream);
|
||||
printed_len += 2;
|
||||
s++;
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
memset (&ps, 0, sizeof (mbstate_t));
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
tlen = mbrlen (s, end - s, &ps);
|
||||
if (MB_INVALIDCH (tlen))
|
||||
{
|
||||
tlen = 1;
|
||||
memset (&ps, 0, sizeof (mbstate_t));
|
||||
}
|
||||
else if (MB_NULLWCH (tlen))
|
||||
break;
|
||||
fwrite (s, 1, tlen, rl_outstream);
|
||||
s += tlen;
|
||||
#else
|
||||
putc (*s, rl_outstream);
|
||||
s++;
|
||||
#endif
|
||||
printed_len++;
|
||||
}
|
||||
}
|
||||
|
||||
return printed_len;
|
||||
}
|
||||
|
||||
/* Output TO_PRINT to rl_outstream. If VISIBLE_STATS is defined and we
|
||||
are using it, check for and output a single character for `special'
|
||||
filenames. Return the number of characters we output. */
|
||||
|
||||
#define PUTX(c) \
|
||||
do { \
|
||||
if (CTRL_CHAR (c)) \
|
||||
{ \
|
||||
putc ('^', rl_outstream); \
|
||||
putc (UNCTRL (c), rl_outstream); \
|
||||
printed_len += 2; \
|
||||
} \
|
||||
else if (c == RUBOUT) \
|
||||
{ \
|
||||
putc ('^', rl_outstream); \
|
||||
putc ('?', rl_outstream); \
|
||||
printed_len += 2; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
putc (c, rl_outstream); \
|
||||
printed_len++; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static int
|
||||
print_filename (to_print, full_pathname)
|
||||
char *to_print, *full_pathname;
|
||||
{
|
||||
int printed_len = 0;
|
||||
#if !defined (VISIBLE_STATS)
|
||||
int printed_len;
|
||||
char *s;
|
||||
|
||||
for (s = to_print; *s; s++)
|
||||
{
|
||||
PUTX (*s);
|
||||
}
|
||||
#else
|
||||
char *s, c, *new_full_pathname;
|
||||
#if defined (VISIBLE_STATS)
|
||||
char c, *new_full_pathname;
|
||||
int extension_char, slen, tlen;
|
||||
#endif
|
||||
|
||||
for (s = to_print; *s; s++)
|
||||
{
|
||||
PUTX (*s);
|
||||
}
|
||||
printed_len = fnprint (to_print);
|
||||
|
||||
#if defined (VISIBLE_STATS)
|
||||
if (rl_filename_completion_desired && rl_visible_stats)
|
||||
{
|
||||
/* If to_print != full_pathname, to_print is the basename of the
|
||||
@@ -612,6 +709,7 @@ print_filename (to_print, full_pathname)
|
||||
}
|
||||
}
|
||||
#endif /* VISIBLE_STATS */
|
||||
|
||||
return printed_len;
|
||||
}
|
||||
|
||||
@@ -663,7 +761,14 @@ _rl_find_completion_word (fp, dp)
|
||||
quote substrings for the completer. Try to find the start
|
||||
of an unclosed quoted substring. */
|
||||
/* FOUND_QUOTE is set so we know what kind of quotes we found. */
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
for (scan = pass_next = 0; scan < end;
|
||||
scan = ((MB_CUR_MAX == 1 || rl_byte_oriented)
|
||||
? (scan + 1)
|
||||
: _rl_find_next_mbchar (rl_line_buffer, scan, 1, MB_FIND_ANY)))
|
||||
#else
|
||||
for (scan = pass_next = 0; scan < end; scan++)
|
||||
#endif
|
||||
{
|
||||
if (pass_next)
|
||||
{
|
||||
@@ -1203,7 +1308,7 @@ display_matches (matches)
|
||||
for (max = 0, i = 1; matches[i]; i++)
|
||||
{
|
||||
temp = printable_part (matches[i]);
|
||||
len = strlen (temp);
|
||||
len = fnwidth (temp);
|
||||
|
||||
if (len > max)
|
||||
max = len;
|
||||
@@ -1449,7 +1554,9 @@ _rl_free_match_list (matches)
|
||||
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. */
|
||||
there is more than one.
|
||||
`@' means to do standard completion, and list all possible completions if
|
||||
there is more than one and partial completion is not possible. */
|
||||
int
|
||||
rl_complete_internal (what_to_do)
|
||||
int what_to_do;
|
||||
@@ -1516,6 +1623,7 @@ rl_complete_internal (what_to_do)
|
||||
{
|
||||
case TAB:
|
||||
case '!':
|
||||
case '@':
|
||||
/* Insert the first match with proper quoting. */
|
||||
if (*matches[0])
|
||||
insert_match (matches[0], start, matches[1] ? MULT_MATCH : SINGLE_MATCH, "e_char);
|
||||
@@ -1535,6 +1643,12 @@ rl_complete_internal (what_to_do)
|
||||
display_matches (matches);
|
||||
break;
|
||||
}
|
||||
else if (what_to_do == '@')
|
||||
{
|
||||
if (nontrivial_lcd == 0)
|
||||
display_matches (matches);
|
||||
break;
|
||||
}
|
||||
else if (rl_editing_mode != vi_mode)
|
||||
rl_ding (); /* There are other matches remaining. */
|
||||
}
|
||||
|
||||
+50
-31
@@ -70,7 +70,7 @@ static void insert_some_chars PARAMS((char *, int, int));
|
||||
static void cr PARAMS((void));
|
||||
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
static int _rl_col_width PARAMS((char *, int, int));
|
||||
static int _rl_col_width PARAMS((const char *, int, int));
|
||||
static int *_rl_wrapped_line;
|
||||
#else
|
||||
# define _rl_col_width(l, s, e) (((e) <= (s)) ? 0 : (e) - (s))
|
||||
@@ -586,7 +586,7 @@ rl_redisplay ()
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
|
||||
{
|
||||
if (wc_bytes == (size_t)-1 || wc_bytes == (size_t)-2)
|
||||
if (MB_INVALIDCH (wc_bytes))
|
||||
{
|
||||
/* Byte sequence is invalid or shortened. Assume that the
|
||||
first byte represents a character. */
|
||||
@@ -595,12 +595,12 @@ rl_redisplay ()
|
||||
wc_width = 1;
|
||||
memset (&ps, 0, sizeof (mbstate_t));
|
||||
}
|
||||
else if (wc_bytes == (size_t)0)
|
||||
else if (MB_NULLWCH (wc_bytes))
|
||||
break; /* Found '\0' */
|
||||
else
|
||||
{
|
||||
temp = wcwidth (wc);
|
||||
wc_width = (temp < 0) ? 1 : temp;
|
||||
wc_width = (temp >= 0) ? temp : 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1069,12 +1069,12 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
|
||||
|
||||
memset (&ps, 0, sizeof (mbstate_t));
|
||||
ret = mbrtowc (&wc, new, MB_CUR_MAX, &ps);
|
||||
if (ret == (size_t)-1 || ret == (size_t)-2)
|
||||
if (MB_INVALIDCH (ret))
|
||||
{
|
||||
tempwidth = 1;
|
||||
ret = 1;
|
||||
}
|
||||
else if (ret == 0)
|
||||
else if (MB_NULLWCH (ret))
|
||||
tempwidth = 0;
|
||||
else
|
||||
tempwidth = wcwidth (wc);
|
||||
@@ -1091,7 +1091,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
|
||||
ret = mbrtowc (&wc, old, MB_CUR_MAX, &ps);
|
||||
if (ret != 0 && bytes != 0)
|
||||
{
|
||||
if (ret == (size_t)-1 || ret == (size_t)-2)
|
||||
if (MB_INVALIDCH (ret))
|
||||
memmove (old+bytes, old+1, strlen (old+1));
|
||||
else
|
||||
memmove (old+bytes, old+ret, strlen (old+ret));
|
||||
@@ -1129,15 +1129,23 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
|
||||
memset (&ps_new, 0, sizeof(mbstate_t));
|
||||
memset (&ps_old, 0, sizeof(mbstate_t));
|
||||
|
||||
new_offset = old_offset = 0;
|
||||
for (ofd = old, nfd = new;
|
||||
(ofd - old < omax) && *ofd &&
|
||||
_rl_compare_chars(old, old_offset, &ps_old, new, new_offset, &ps_new); )
|
||||
if (omax == nmax && STREQN (new, old, omax))
|
||||
{
|
||||
old_offset = _rl_find_next_mbchar (old, old_offset, 1, MB_FIND_ANY);
|
||||
new_offset = _rl_find_next_mbchar (new, new_offset, 1, MB_FIND_ANY);
|
||||
ofd = old + old_offset;
|
||||
nfd = new + new_offset;
|
||||
ofd = old + omax;
|
||||
nfd = new + nmax;
|
||||
}
|
||||
else
|
||||
{
|
||||
new_offset = old_offset = 0;
|
||||
for (ofd = old, nfd = new;
|
||||
(ofd - old < omax) && *ofd &&
|
||||
_rl_compare_chars(old, old_offset, &ps_old, new, new_offset, &ps_new); )
|
||||
{
|
||||
old_offset = _rl_find_next_mbchar (old, old_offset, 1, MB_FIND_ANY);
|
||||
new_offset = _rl_find_next_mbchar (new, new_offset, 1, MB_FIND_ANY);
|
||||
ofd = old + old_offset;
|
||||
nfd = new + new_offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1169,8 +1177,11 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
|
||||
memset (&ps_old, 0, sizeof (mbstate_t));
|
||||
memset (&ps_new, 0, sizeof (mbstate_t));
|
||||
|
||||
#if 0
|
||||
/* On advice from jir@yamato.ibm.com */
|
||||
_rl_adjust_point (old, ols - old, &ps_old);
|
||||
_rl_adjust_point (new, nls - new, &ps_new);
|
||||
#endif
|
||||
|
||||
if (_rl_compare_chars (old, ols - old, &ps_old, new, nls - new, &ps_new) == 0)
|
||||
break;
|
||||
@@ -1324,7 +1335,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
|
||||
insert_some_chars (nfd, lendiff, col_lendiff);
|
||||
_rl_last_c_pos += col_lendiff;
|
||||
}
|
||||
else if (*ols == 0)
|
||||
else if (*ols == 0 && lendiff > 0)
|
||||
{
|
||||
/* At the end of a line the characters do not have to
|
||||
be "inserted". They can just be placed on the screen. */
|
||||
@@ -1348,9 +1359,9 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
|
||||
{
|
||||
_rl_output_some_chars (nfd + lendiff, temp - lendiff);
|
||||
#if 0
|
||||
_rl_last_c_pos += _rl_col_width (nfd+lendiff, 0, temp-lendiff) - col_lendiff;
|
||||
#else
|
||||
_rl_last_c_pos += _rl_col_width (nfd+lendiff, 0, temp-col_lendiff);
|
||||
#else
|
||||
_rl_last_c_pos += _rl_col_width (nfd+lendiff, 0, temp-lendiff);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -1510,8 +1521,15 @@ _rl_move_cursor_relative (new, data)
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
/* If we have multibyte characters, NEW is indexed by the buffer point in
|
||||
a multibyte string, but _rl_last_c_pos is the display position. In
|
||||
this case, NEW's display position is not obvious. */
|
||||
if ((MB_CUR_MAX == 1 || rl_byte_oriented ) && _rl_last_c_pos == new) return;
|
||||
this case, NEW's display position is not obvious and must be
|
||||
calculated. */
|
||||
if (MB_CUR_MAX == 1 || rl_byte_oriented)
|
||||
{
|
||||
if (_rl_last_c_pos == new)
|
||||
return;
|
||||
}
|
||||
else if (_rl_last_c_pos == _rl_col_width (data, 0, new))
|
||||
return;
|
||||
#else
|
||||
if (_rl_last_c_pos == new) return;
|
||||
#endif
|
||||
@@ -1594,11 +1612,7 @@ _rl_move_cursor_relative (new, data)
|
||||
#endif
|
||||
{
|
||||
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
|
||||
{
|
||||
tputs (_rl_term_cr, 1, _rl_output_character_function);
|
||||
for (i = 0; i < new; i++)
|
||||
putc (data[i], rl_outstream);
|
||||
}
|
||||
_rl_backspace (_rl_last_c_pos - _rl_col_width (data, 0, new));
|
||||
else
|
||||
_rl_backspace (_rl_last_c_pos - new);
|
||||
}
|
||||
@@ -1764,10 +1778,13 @@ rl_reset_line_state ()
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* These are getting numerous enough that it's time to create a struct. */
|
||||
|
||||
static char *saved_local_prompt;
|
||||
static char *saved_local_prefix;
|
||||
static int saved_last_invisible;
|
||||
static int saved_visible_length;
|
||||
static int saved_invis_chars_first_line;
|
||||
|
||||
void
|
||||
rl_save_prompt ()
|
||||
@@ -1776,9 +1793,11 @@ rl_save_prompt ()
|
||||
saved_local_prefix = local_prompt_prefix;
|
||||
saved_last_invisible = prompt_last_invisible;
|
||||
saved_visible_length = prompt_visible_length;
|
||||
saved_invis_chars_first_line = prompt_invis_chars_first_line;
|
||||
|
||||
local_prompt = local_prompt_prefix = (char *)0;
|
||||
prompt_last_invisible = prompt_visible_length = 0;
|
||||
prompt_invis_chars_first_line = 0;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1791,6 +1810,7 @@ rl_restore_prompt ()
|
||||
local_prompt_prefix = saved_local_prefix;
|
||||
prompt_last_invisible = saved_last_invisible;
|
||||
prompt_visible_length = saved_visible_length;
|
||||
prompt_invis_chars_first_line = saved_invis_chars_first_line;
|
||||
}
|
||||
|
||||
char *
|
||||
@@ -2117,7 +2137,7 @@ _rl_current_display_line ()
|
||||
scan from the beginning of the string to take the state into account. */
|
||||
static int
|
||||
_rl_col_width (str, start, end)
|
||||
char *str;
|
||||
const char *str;
|
||||
int start, end;
|
||||
{
|
||||
wchar_t wc;
|
||||
@@ -2133,7 +2153,7 @@ _rl_col_width (str, start, end)
|
||||
while (point < start)
|
||||
{
|
||||
tmp = mbrlen (str + point, max, &ps);
|
||||
if ((size_t)tmp == (size_t)-1 || (size_t)tmp == (size_t)-2)
|
||||
if (MB_INVALIDCH ((size_t)tmp))
|
||||
{
|
||||
/* In this case, the bytes are invalid or too short to compose a
|
||||
multibyte character, so we assume that the first byte represents
|
||||
@@ -2145,7 +2165,7 @@ _rl_col_width (str, start, end)
|
||||
effect of mbstate is undefined. */
|
||||
memset (&ps, 0, sizeof (mbstate_t));
|
||||
}
|
||||
else if (tmp == 0)
|
||||
else if (MB_NULLWCH (tmp))
|
||||
break; /* Found '\0' */
|
||||
else
|
||||
{
|
||||
@@ -2162,7 +2182,7 @@ _rl_col_width (str, start, end)
|
||||
while (point < end)
|
||||
{
|
||||
tmp = mbrtowc (&wc, str + point, max, &ps);
|
||||
if ((size_t)tmp == (size_t)-1 || (size_t)tmp == (size_t)-2)
|
||||
if (MB_INVALIDCH ((size_t)tmp))
|
||||
{
|
||||
/* In this case, the bytes are invalid or too short to compose a
|
||||
multibyte character, so we assume that the first byte represents
|
||||
@@ -2177,7 +2197,7 @@ _rl_col_width (str, start, end)
|
||||
effect of mbstate is undefined. */
|
||||
memset (&ps, 0, sizeof (mbstate_t));
|
||||
}
|
||||
else if (tmp == 0)
|
||||
else if (MB_NULLWCH (tmp))
|
||||
break; /* Found '\0' */
|
||||
else
|
||||
{
|
||||
@@ -2193,4 +2213,3 @@ _rl_col_width (str, start, end)
|
||||
return width;
|
||||
}
|
||||
#endif /* HANDLE_MULTIBYTE */
|
||||
|
||||
|
||||
+15
-18
@@ -49,11 +49,11 @@ QUIETPS = #set this to -q to shut up dvips
|
||||
PSDPI = 300 # I don't have any 600-dpi printers
|
||||
DVIPS = dvips -D ${PSDPI} $(QUIETPS) -o $@ # tricky
|
||||
|
||||
RLSRC = $(srcdir)/rlman.texinfo $(srcdir)/rluser.texinfo \
|
||||
$(srcdir)/rltech.texinfo $(srcdir)/manvers.texinfo \
|
||||
$(srcdir)/rluserman.texinfo
|
||||
HISTSRC = $(srcdir)/hist.texinfo $(srcdir)/hsuser.texinfo \
|
||||
$(srcdir)/hstech.texinfo $(srcdir)/manvers.texinfo
|
||||
RLSRC = $(srcdir)/rlman.texi $(srcdir)/rluser.texi \
|
||||
$(srcdir)/rltech.texi $(srcdir)/version.texi \
|
||||
$(srcdir)/rluserman.texi
|
||||
HISTSRC = $(srcdir)/history.texi $(srcdir)/hsuser.texi \
|
||||
$(srcdir)/hstech.texi $(srcdir)/version.texi
|
||||
|
||||
# This should be a program that converts troff to an ascii-readable format
|
||||
NROFF = groff -Tascii
|
||||
@@ -66,7 +66,7 @@ INFOOBJ = readline.info history.info rluserman.info
|
||||
PSOBJ = readline.ps history.ps rluserman.ps
|
||||
HTMLOBJ = readline.html history.html rluserman.html
|
||||
|
||||
INTERMEDIATE_OBJ = rlman.dvi hist.dvi rluserman.dvi
|
||||
INTERMEDIATE_OBJ = rlman.dvi
|
||||
|
||||
CREATED_DOCS = $(DVIOBJ) $(INFOOBJ) $(PSOBJ) $(HTMLOBJ)
|
||||
|
||||
@@ -76,24 +76,23 @@ all: info dvi html ps
|
||||
nodvi: info html
|
||||
|
||||
readline.dvi: $(RLSRC)
|
||||
TEXINPUTS=.:$(TEXINPUTDIR):$$TEXINPUTS $(TEXI2DVI) $(srcdir)/rlman.texinfo
|
||||
TEXINPUTS=.:$(TEXINPUTDIR):$$TEXINPUTS $(TEXI2DVI) $(srcdir)/rlman.texi
|
||||
mv rlman.dvi readline.dvi
|
||||
|
||||
readline.info: $(RLSRC)
|
||||
$(MAKEINFO) --no-split -I $(TEXINPUTDIR) -o $@ $(srcdir)/rlman.texinfo
|
||||
$(MAKEINFO) --no-split -I $(TEXINPUTDIR) -o $@ $(srcdir)/rlman.texi
|
||||
|
||||
rluserman.dvi: $(RLSRC)
|
||||
TEXINPUTS=.:$(TEXINPUTDIR):$$TEXINPUTS $(TEXI2DVI) $(srcdir)/rluserman.texinfo
|
||||
TEXINPUTS=.:$(TEXINPUTDIR):$$TEXINPUTS $(TEXI2DVI) $(srcdir)/rluserman.texi
|
||||
|
||||
rluserman.info: $(RLSRC)
|
||||
$(MAKEINFO) --no-split -I $(TEXINPUTDIR) -o $@ $(srcdir)/rluserman.texinfo
|
||||
$(MAKEINFO) --no-split -I $(TEXINPUTDIR) -o $@ $(srcdir)/rluserman.texi
|
||||
|
||||
history.dvi: ${HISTSRC}
|
||||
TEXINPUTS=.:$(TEXINPUTDIR):$$TEXINPUTS $(TEXI2DVI) $(srcdir)/hist.texinfo
|
||||
mv hist.dvi history.dvi
|
||||
TEXINPUTS=.:$(TEXINPUTDIR):$$TEXINPUTS $(TEXI2DVI) $(srcdir)/history.texi
|
||||
|
||||
history.info: ${HISTSRC}
|
||||
$(MAKEINFO) --no-split -I $(TEXINPUTDIR) -o $@ $(srcdir)/hist.texinfo
|
||||
$(MAKEINFO) --no-split -I $(TEXINPUTDIR) -o $@ $(srcdir)/history.texi
|
||||
|
||||
readline.ps: readline.dvi
|
||||
$(RM) $@
|
||||
@@ -108,17 +107,15 @@ history.ps: history.dvi
|
||||
$(DVIPS) history.dvi
|
||||
|
||||
readline.html: ${RLSRC}
|
||||
$(TEXI2HTML) -menu -monolithic -I $(TEXINPUTDIR) $(srcdir)/rlman.texinfo
|
||||
$(TEXI2HTML) -menu -monolithic -I $(TEXINPUTDIR) $(srcdir)/rlman.texi
|
||||
sed -e 's:rlman.html:readline.html:' rlman.html > readline.html
|
||||
$(RM) rlman.html
|
||||
|
||||
rluserman.html: ${RLSRC}
|
||||
$(TEXI2HTML) -menu -monolithic -I $(TEXINPUTDIR) $(srcdir)/rluserman.texinfo
|
||||
$(TEXI2HTML) -menu -monolithic -I $(TEXINPUTDIR) $(srcdir)/rluserman.texi
|
||||
|
||||
history.html: ${HISTSRC}
|
||||
$(TEXI2HTML) -menu -monolithic -I $(TEXINPUTDIR) $(srcdir)/hist.texinfo
|
||||
sed -e 's:hist.html:history.html:' hist.html > history.html
|
||||
$(RM) hist.html
|
||||
$(TEXI2HTML) -menu -monolithic -I $(TEXINPUTDIR) $(srcdir)/history.texi
|
||||
|
||||
info: $(INFOOBJ)
|
||||
dvi: $(DVIOBJ)
|
||||
|
||||
@@ -0,0 +1,452 @@
|
||||
|
||||
@node GNU Free Documentation License
|
||||
@appendixsec GNU Free Documentation License
|
||||
|
||||
@cindex FDL, GNU Free Documentation License
|
||||
@center Version 1.2, November 2002
|
||||
|
||||
@display
|
||||
Copyright @copyright{} 2000,2001,2002 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
@end display
|
||||
|
||||
@enumerate 0
|
||||
@item
|
||||
PREAMBLE
|
||||
|
||||
The purpose of this License is to make a manual, textbook, or other
|
||||
functional and useful document @dfn{free} in the sense of freedom: to
|
||||
assure everyone the effective freedom to copy and redistribute it,
|
||||
with or without modifying it, either commercially or noncommercially.
|
||||
Secondarily, this License preserves for the author and publisher a way
|
||||
to get credit for their work, while not being considered responsible
|
||||
for modifications made by others.
|
||||
|
||||
This License is a kind of ``copyleft'', which means that derivative
|
||||
works of the document must themselves be free in the same sense. It
|
||||
complements the GNU General Public License, which is a copyleft
|
||||
license designed for free software.
|
||||
|
||||
We have designed this License in order to use it for manuals for free
|
||||
software, because free software needs free documentation: a free
|
||||
program should come with manuals providing the same freedoms that the
|
||||
software does. But this License is not limited to software manuals;
|
||||
it can be used for any textual work, regardless of subject matter or
|
||||
whether it is published as a printed book. We recommend this License
|
||||
principally for works whose purpose is instruction or reference.
|
||||
|
||||
@item
|
||||
APPLICABILITY AND DEFINITIONS
|
||||
|
||||
This License applies to any manual or other work, in any medium, that
|
||||
contains a notice placed by the copyright holder saying it can be
|
||||
distributed under the terms of this License. Such a notice grants a
|
||||
world-wide, royalty-free license, unlimited in duration, to use that
|
||||
work under the conditions stated herein. The ``Document'', below,
|
||||
refers to any such manual or work. Any member of the public is a
|
||||
licensee, and is addressed as ``you''. You accept the license if you
|
||||
copy, modify or distribute the work in a way requiring permission
|
||||
under copyright law.
|
||||
|
||||
A ``Modified Version'' of the Document means any work containing the
|
||||
Document or a portion of it, either copied verbatim, or with
|
||||
modifications and/or translated into another language.
|
||||
|
||||
A ``Secondary Section'' is a named appendix or a front-matter section
|
||||
of the Document that deals exclusively with the relationship of the
|
||||
publishers or authors of the Document to the Document's overall
|
||||
subject (or to related matters) and contains nothing that could fall
|
||||
directly within that overall subject. (Thus, if the Document is in
|
||||
part a textbook of mathematics, a Secondary Section may not explain
|
||||
any mathematics.) The relationship could be a matter of historical
|
||||
connection with the subject or with related matters, or of legal,
|
||||
commercial, philosophical, ethical or political position regarding
|
||||
them.
|
||||
|
||||
The ``Invariant Sections'' are certain Secondary Sections whose titles
|
||||
are designated, as being those of Invariant Sections, in the notice
|
||||
that says that the Document is released under this License. If a
|
||||
section does not fit the above definition of Secondary then it is not
|
||||
allowed to be designated as Invariant. The Document may contain zero
|
||||
Invariant Sections. If the Document does not identify any Invariant
|
||||
Sections then there are none.
|
||||
|
||||
The ``Cover Texts'' are certain short passages of text that are listed,
|
||||
as Front-Cover Texts or Back-Cover Texts, in the notice that says that
|
||||
the Document is released under this License. A Front-Cover Text may
|
||||
be at most 5 words, and a Back-Cover Text may be at most 25 words.
|
||||
|
||||
A ``Transparent'' copy of the Document means a machine-readable copy,
|
||||
represented in a format whose specification is available to the
|
||||
general public, that is suitable for revising the document
|
||||
straightforwardly with generic text editors or (for images composed of
|
||||
pixels) generic paint programs or (for drawings) some widely available
|
||||
drawing editor, and that is suitable for input to text formatters or
|
||||
for automatic translation to a variety of formats suitable for input
|
||||
to text formatters. A copy made in an otherwise Transparent file
|
||||
format whose markup, or absence of markup, has been arranged to thwart
|
||||
or discourage subsequent modification by readers is not Transparent.
|
||||
An image format is not Transparent if used for any substantial amount
|
||||
of text. A copy that is not ``Transparent'' is called ``Opaque''.
|
||||
|
||||
Examples of suitable formats for Transparent copies include plain
|
||||
@sc{ascii} without markup, Texinfo input format, La@TeX{} input
|
||||
format, @acronym{SGML} or @acronym{XML} using a publicly available
|
||||
@acronym{DTD}, and standard-conforming simple @acronym{HTML},
|
||||
PostScript or @acronym{PDF} designed for human modification. Examples
|
||||
of transparent image formats include @acronym{PNG}, @acronym{XCF} and
|
||||
@acronym{JPG}. Opaque formats include proprietary formats that can be
|
||||
read and edited only by proprietary word processors, @acronym{SGML} or
|
||||
@acronym{XML} for which the @acronym{DTD} and/or processing tools are
|
||||
not generally available, and the machine-generated @acronym{HTML},
|
||||
PostScript or @acronym{PDF} produced by some word processors for
|
||||
output purposes only.
|
||||
|
||||
The ``Title Page'' means, for a printed book, the title page itself,
|
||||
plus such following pages as are needed to hold, legibly, the material
|
||||
this License requires to appear in the title page. For works in
|
||||
formats which do not have any title page as such, ``Title Page'' means
|
||||
the text near the most prominent appearance of the work's title,
|
||||
preceding the beginning of the body of the text.
|
||||
|
||||
A section ``Entitled XYZ'' means a named subunit of the Document whose
|
||||
title either is precisely XYZ or contains XYZ in parentheses following
|
||||
text that translates XYZ in another language. (Here XYZ stands for a
|
||||
specific section name mentioned below, such as ``Acknowledgements'',
|
||||
``Dedications'', ``Endorsements'', or ``History''.) To ``Preserve the Title''
|
||||
of such a section when you modify the Document means that it remains a
|
||||
section ``Entitled XYZ'' according to this definition.
|
||||
|
||||
The Document may include Warranty Disclaimers next to the notice which
|
||||
states that this License applies to the Document. These Warranty
|
||||
Disclaimers are considered to be included by reference in this
|
||||
License, but only as regards disclaiming warranties: any other
|
||||
implication that these Warranty Disclaimers may have is void and has
|
||||
no effect on the meaning of this License.
|
||||
|
||||
@item
|
||||
VERBATIM COPYING
|
||||
|
||||
You may copy and distribute the Document in any medium, either
|
||||
commercially or noncommercially, provided that this License, the
|
||||
copyright notices, and the license notice saying this License applies
|
||||
to the Document are reproduced in all copies, and that you add no other
|
||||
conditions whatsoever to those of this License. You may not use
|
||||
technical measures to obstruct or control the reading or further
|
||||
copying of the copies you make or distribute. However, you may accept
|
||||
compensation in exchange for copies. If you distribute a large enough
|
||||
number of copies you must also follow the conditions in section 3.
|
||||
|
||||
You may also lend copies, under the same conditions stated above, and
|
||||
you may publicly display copies.
|
||||
|
||||
@item
|
||||
COPYING IN QUANTITY
|
||||
|
||||
If you publish printed copies (or copies in media that commonly have
|
||||
printed covers) of the Document, numbering more than 100, and the
|
||||
Document's license notice requires Cover Texts, you must enclose the
|
||||
copies in covers that carry, clearly and legibly, all these Cover
|
||||
Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on
|
||||
the back cover. Both covers must also clearly and legibly identify
|
||||
you as the publisher of these copies. The front cover must present
|
||||
the full title with all words of the title equally prominent and
|
||||
visible. You may add other material on the covers in addition.
|
||||
Copying with changes limited to the covers, as long as they preserve
|
||||
the title of the Document and satisfy these conditions, can be treated
|
||||
as verbatim copying in other respects.
|
||||
|
||||
If the required texts for either cover are too voluminous to fit
|
||||
legibly, you should put the first ones listed (as many as fit
|
||||
reasonably) on the actual cover, and continue the rest onto adjacent
|
||||
pages.
|
||||
|
||||
If you publish or distribute Opaque copies of the Document numbering
|
||||
more than 100, you must either include a machine-readable Transparent
|
||||
copy along with each Opaque copy, or state in or with each Opaque copy
|
||||
a computer-network location from which the general network-using
|
||||
public has access to download using public-standard network protocols
|
||||
a complete Transparent copy of the Document, free of added material.
|
||||
If you use the latter option, you must take reasonably prudent steps,
|
||||
when you begin distribution of Opaque copies in quantity, to ensure
|
||||
that this Transparent copy will remain thus accessible at the stated
|
||||
location until at least one year after the last time you distribute an
|
||||
Opaque copy (directly or through your agents or retailers) of that
|
||||
edition to the public.
|
||||
|
||||
It is requested, but not required, that you contact the authors of the
|
||||
Document well before redistributing any large number of copies, to give
|
||||
them a chance to provide you with an updated version of the Document.
|
||||
|
||||
@item
|
||||
MODIFICATIONS
|
||||
|
||||
You may copy and distribute a Modified Version of the Document under
|
||||
the conditions of sections 2 and 3 above, provided that you release
|
||||
the Modified Version under precisely this License, with the Modified
|
||||
Version filling the role of the Document, thus licensing distribution
|
||||
and modification of the Modified Version to whoever possesses a copy
|
||||
of it. In addition, you must do these things in the Modified Version:
|
||||
|
||||
@enumerate A
|
||||
@item
|
||||
Use in the Title Page (and on the covers, if any) a title distinct
|
||||
from that of the Document, and from those of previous versions
|
||||
(which should, if there were any, be listed in the History section
|
||||
of the Document). You may use the same title as a previous version
|
||||
if the original publisher of that version gives permission.
|
||||
|
||||
@item
|
||||
List on the Title Page, as authors, one or more persons or entities
|
||||
responsible for authorship of the modifications in the Modified
|
||||
Version, together with at least five of the principal authors of the
|
||||
Document (all of its principal authors, if it has fewer than five),
|
||||
unless they release you from this requirement.
|
||||
|
||||
@item
|
||||
State on the Title page the name of the publisher of the
|
||||
Modified Version, as the publisher.
|
||||
|
||||
@item
|
||||
Preserve all the copyright notices of the Document.
|
||||
|
||||
@item
|
||||
Add an appropriate copyright notice for your modifications
|
||||
adjacent to the other copyright notices.
|
||||
|
||||
@item
|
||||
Include, immediately after the copyright notices, a license notice
|
||||
giving the public permission to use the Modified Version under the
|
||||
terms of this License, in the form shown in the Addendum below.
|
||||
|
||||
@item
|
||||
Preserve in that license notice the full lists of Invariant Sections
|
||||
and required Cover Texts given in the Document's license notice.
|
||||
|
||||
@item
|
||||
Include an unaltered copy of this License.
|
||||
|
||||
@item
|
||||
Preserve the section Entitled ``History'', Preserve its Title, and add
|
||||
to it an item stating at least the title, year, new authors, and
|
||||
publisher of the Modified Version as given on the Title Page. If
|
||||
there is no section Entitled ``History'' in the Document, create one
|
||||
stating the title, year, authors, and publisher of the Document as
|
||||
given on its Title Page, then add an item describing the Modified
|
||||
Version as stated in the previous sentence.
|
||||
|
||||
@item
|
||||
Preserve the network location, if any, given in the Document for
|
||||
public access to a Transparent copy of the Document, and likewise
|
||||
the network locations given in the Document for previous versions
|
||||
it was based on. These may be placed in the ``History'' section.
|
||||
You may omit a network location for a work that was published at
|
||||
least four years before the Document itself, or if the original
|
||||
publisher of the version it refers to gives permission.
|
||||
|
||||
@item
|
||||
For any section Entitled ``Acknowledgements'' or ``Dedications'', Preserve
|
||||
the Title of the section, and preserve in the section all the
|
||||
substance and tone of each of the contributor acknowledgements and/or
|
||||
dedications given therein.
|
||||
|
||||
@item
|
||||
Preserve all the Invariant Sections of the Document,
|
||||
unaltered in their text and in their titles. Section numbers
|
||||
or the equivalent are not considered part of the section titles.
|
||||
|
||||
@item
|
||||
Delete any section Entitled ``Endorsements''. Such a section
|
||||
may not be included in the Modified Version.
|
||||
|
||||
@item
|
||||
Do not retitle any existing section to be Entitled ``Endorsements'' or
|
||||
to conflict in title with any Invariant Section.
|
||||
|
||||
@item
|
||||
Preserve any Warranty Disclaimers.
|
||||
@end enumerate
|
||||
|
||||
If the Modified Version includes new front-matter sections or
|
||||
appendices that qualify as Secondary Sections and contain no material
|
||||
copied from the Document, you may at your option designate some or all
|
||||
of these sections as invariant. To do this, add their titles to the
|
||||
list of Invariant Sections in the Modified Version's license notice.
|
||||
These titles must be distinct from any other section titles.
|
||||
|
||||
You may add a section Entitled ``Endorsements'', provided it contains
|
||||
nothing but endorsements of your Modified Version by various
|
||||
parties---for example, statements of peer review or that the text has
|
||||
been approved by an organization as the authoritative definition of a
|
||||
standard.
|
||||
|
||||
You may add a passage of up to five words as a Front-Cover Text, and a
|
||||
passage of up to 25 words as a Back-Cover Text, to the end of the list
|
||||
of Cover Texts in the Modified Version. Only one passage of
|
||||
Front-Cover Text and one of Back-Cover Text may be added by (or
|
||||
through arrangements made by) any one entity. If the Document already
|
||||
includes a cover text for the same cover, previously added by you or
|
||||
by arrangement made by the same entity you are acting on behalf of,
|
||||
you may not add another; but you may replace the old one, on explicit
|
||||
permission from the previous publisher that added the old one.
|
||||
|
||||
The author(s) and publisher(s) of the Document do not by this License
|
||||
give permission to use their names for publicity for or to assert or
|
||||
imply endorsement of any Modified Version.
|
||||
|
||||
@item
|
||||
COMBINING DOCUMENTS
|
||||
|
||||
You may combine the Document with other documents released under this
|
||||
License, under the terms defined in section 4 above for modified
|
||||
versions, provided that you include in the combination all of the
|
||||
Invariant Sections of all of the original documents, unmodified, and
|
||||
list them all as Invariant Sections of your combined work in its
|
||||
license notice, and that you preserve all their Warranty Disclaimers.
|
||||
|
||||
The combined work need only contain one copy of this License, and
|
||||
multiple identical Invariant Sections may be replaced with a single
|
||||
copy. If there are multiple Invariant Sections with the same name but
|
||||
different contents, make the title of each such section unique by
|
||||
adding at the end of it, in parentheses, the name of the original
|
||||
author or publisher of that section if known, or else a unique number.
|
||||
Make the same adjustment to the section titles in the list of
|
||||
Invariant Sections in the license notice of the combined work.
|
||||
|
||||
In the combination, you must combine any sections Entitled ``History''
|
||||
in the various original documents, forming one section Entitled
|
||||
``History''; likewise combine any sections Entitled ``Acknowledgements'',
|
||||
and any sections Entitled ``Dedications''. You must delete all
|
||||
sections Entitled ``Endorsements.''
|
||||
|
||||
@item
|
||||
COLLECTIONS OF DOCUMENTS
|
||||
|
||||
You may make a collection consisting of the Document and other documents
|
||||
released under this License, and replace the individual copies of this
|
||||
License in the various documents with a single copy that is included in
|
||||
the collection, provided that you follow the rules of this License for
|
||||
verbatim copying of each of the documents in all other respects.
|
||||
|
||||
You may extract a single document from such a collection, and distribute
|
||||
it individually under this License, provided you insert a copy of this
|
||||
License into the extracted document, and follow this License in all
|
||||
other respects regarding verbatim copying of that document.
|
||||
|
||||
@item
|
||||
AGGREGATION WITH INDEPENDENT WORKS
|
||||
|
||||
A compilation of the Document or its derivatives with other separate
|
||||
and independent documents or works, in or on a volume of a storage or
|
||||
distribution medium, is called an ``aggregate'' if the copyright
|
||||
resulting from the compilation is not used to limit the legal rights
|
||||
of the compilation's users beyond what the individual works permit.
|
||||
When the Document is included an aggregate, this License does not
|
||||
apply to the other works in the aggregate which are not themselves
|
||||
derivative works of the Document.
|
||||
|
||||
If the Cover Text requirement of section 3 is applicable to these
|
||||
copies of the Document, then if the Document is less than one half of
|
||||
the entire aggregate, the Document's Cover Texts may be placed on
|
||||
covers that bracket the Document within the aggregate, or the
|
||||
electronic equivalent of covers if the Document is in electronic form.
|
||||
Otherwise they must appear on printed covers that bracket the whole
|
||||
aggregate.
|
||||
|
||||
@item
|
||||
TRANSLATION
|
||||
|
||||
Translation is considered a kind of modification, so you may
|
||||
distribute translations of the Document under the terms of section 4.
|
||||
Replacing Invariant Sections with translations requires special
|
||||
permission from their copyright holders, but you may include
|
||||
translations of some or all Invariant Sections in addition to the
|
||||
original versions of these Invariant Sections. You may include a
|
||||
translation of this License, and all the license notices in the
|
||||
Document, and any Warranty Disclaimers, provided that you also include
|
||||
the original English version of this License and the original versions
|
||||
of those notices and disclaimers. In case of a disagreement between
|
||||
the translation and the original version of this License or a notice
|
||||
or disclaimer, the original version will prevail.
|
||||
|
||||
If a section in the Document is Entitled ``Acknowledgements'',
|
||||
``Dedications'', or ``History'', the requirement (section 4) to Preserve
|
||||
its Title (section 1) will typically require changing the actual
|
||||
title.
|
||||
|
||||
@item
|
||||
TERMINATION
|
||||
|
||||
You may not copy, modify, sublicense, or distribute the Document except
|
||||
as expressly provided for under this License. Any other attempt to
|
||||
copy, modify, sublicense or distribute the Document is void, and will
|
||||
automatically terminate your rights under this License. However,
|
||||
parties who have received copies, or rights, from you under this
|
||||
License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
@item
|
||||
FUTURE REVISIONS OF THIS LICENSE
|
||||
|
||||
The Free Software Foundation may publish new, revised versions
|
||||
of the GNU Free Documentation License from time to time. Such new
|
||||
versions will be similar in spirit to the present version, but may
|
||||
differ in detail to address new problems or concerns. See
|
||||
@uref{http://www.gnu.org/copyleft/}.
|
||||
|
||||
Each version of the License is given a distinguishing version number.
|
||||
If the Document specifies that a particular numbered version of this
|
||||
License ``or any later version'' applies to it, you have the option of
|
||||
following the terms and conditions either of that specified version or
|
||||
of any later version that has been published (not as a draft) by the
|
||||
Free Software Foundation. If the Document does not specify a version
|
||||
number of this License, you may choose any version ever published (not
|
||||
as a draft) by the Free Software Foundation.
|
||||
@end enumerate
|
||||
|
||||
@page
|
||||
@appendixsubsec ADDENDUM: How to use this License for your documents
|
||||
|
||||
To use this License in a document you have written, include a copy of
|
||||
the License in the document and put the following copyright and
|
||||
license notices just after the title page:
|
||||
|
||||
@smallexample
|
||||
@group
|
||||
Copyright (C) @var{year} @var{your name}.
|
||||
Permission is granted to copy, distribute and/or modify this document
|
||||
under the terms of the GNU Free Documentation License, Version 1.2
|
||||
or any later version published by the Free Software Foundation;
|
||||
with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
|
||||
A copy of the license is included in the section entitled ``GNU
|
||||
Free Documentation License''.
|
||||
@end group
|
||||
@end smallexample
|
||||
|
||||
If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts,
|
||||
replace the ``with...Texts.'' line with this:
|
||||
|
||||
@smallexample
|
||||
@group
|
||||
with the Invariant Sections being @var{list their titles}, with
|
||||
the Front-Cover Texts being @var{list}, and with the Back-Cover Texts
|
||||
being @var{list}.
|
||||
@end group
|
||||
@end smallexample
|
||||
|
||||
If you have Invariant Sections without Cover Texts, or some other
|
||||
combination of the three, merge those two alternatives to suit the
|
||||
situation.
|
||||
|
||||
If your document contains nontrivial examples of program code, we
|
||||
recommend releasing these examples in parallel under your choice of
|
||||
free software license, such as the GNU General Public License,
|
||||
to permit their use in free software.
|
||||
|
||||
@c Local Variables:
|
||||
@c ispell-local-pdict: "ispell-dict"
|
||||
@c End:
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
\input texinfo @c -*-texinfo-*-
|
||||
@c %**start of header (This is for running Texinfo on a region.)
|
||||
@setfilename history.info
|
||||
@settitle GNU History Library
|
||||
@c %**end of header (This is for running Texinfo on a region.)
|
||||
|
||||
@setchapternewpage odd
|
||||
|
||||
@include version.texi
|
||||
|
||||
@copying
|
||||
This document describes the GNU History library
|
||||
(version @value{VERSION}, @value{UPDATED}),
|
||||
a programming tool that provides a consistent user interface for
|
||||
recalling lines of previously typed input.
|
||||
|
||||
Copyright @copyright{} 1988-2003 Free Software Foundation, Inc.
|
||||
|
||||
Permission is granted to make and distribute verbatim copies of
|
||||
this manual provided the copyright notice and this permission notice
|
||||
are preserved on all copies.
|
||||
|
||||
@quotation
|
||||
Permission is granted to copy, distribute and/or modify this document
|
||||
under the terms of the GNU Free Documentation License, Version 1.1 or
|
||||
any later version published by the Free Software Foundation; with no
|
||||
Invariant Sections, with the Front-Cover texts being ``A GNU Manual,''
|
||||
and with the Back-Cover Texts as in (a) below. A copy of the license is
|
||||
included in the section entitled ``GNU Free Documentation License.''
|
||||
|
||||
(a) The FSF's Back-Cover Text is: ``You have freedom to copy and modify
|
||||
this GNU Manual, like GNU software. Copies published by the Free
|
||||
Software Foundation raise funds for GNU development.''
|
||||
@end quotation
|
||||
@end copying
|
||||
|
||||
@dircategory Libraries
|
||||
@direntry
|
||||
* History: (history). The GNU history library API.
|
||||
@end direntry
|
||||
|
||||
@titlepage
|
||||
@title GNU History Library
|
||||
@subtitle Edition @value{EDITION}, for @code{History Library} Version @value{VERSION}.
|
||||
@subtitle @value{UPDATED-MONTH}
|
||||
@author Chet Ramey, Case Western Reserve University
|
||||
@author Brian Fox, Free Software Foundation
|
||||
|
||||
@page
|
||||
|
||||
@vskip 0pt plus 1filll
|
||||
@insertcopying
|
||||
|
||||
@sp 1
|
||||
Published by the Free Software Foundation @*
|
||||
59 Temple Place, Suite 330, @*
|
||||
Boston, MA 02111-1307 @*
|
||||
USA @*
|
||||
|
||||
@end titlepage
|
||||
|
||||
@contents
|
||||
|
||||
@ifnottex
|
||||
@node Top
|
||||
@top GNU History Library
|
||||
|
||||
This document describes the GNU History library, a programming tool that
|
||||
provides a consistent user interface for recalling lines of previously
|
||||
typed input.
|
||||
|
||||
@menu
|
||||
* Using History Interactively:: GNU History User's Manual.
|
||||
* Programming with GNU History:: GNU History Programmer's Manual.
|
||||
* Copying This Manual:: Copying This Manual.
|
||||
* Concept Index:: Index of concepts described in this manual.
|
||||
* Function and Variable Index:: Index of externally visible functions
|
||||
and variables.
|
||||
@end menu
|
||||
@end ifnottex
|
||||
|
||||
@syncodeindex fn vr
|
||||
|
||||
@include hsuser.texi
|
||||
@include hstech.texi
|
||||
|
||||
@node Copying This Manual
|
||||
@appendix Copying This Manual
|
||||
|
||||
@menu
|
||||
* GNU Free Documentation License:: License for copying this manual.
|
||||
@end menu
|
||||
|
||||
@include fdl.texi
|
||||
|
||||
@node Concept Index
|
||||
@appendix Concept Index
|
||||
@printindex cp
|
||||
|
||||
@node Function and Variable Index
|
||||
@appendix Function and Variable Index
|
||||
@printindex vr
|
||||
|
||||
@bye
|
||||
@@ -0,0 +1,573 @@
|
||||
@ignore
|
||||
This file documents the user interface to the GNU History library.
|
||||
|
||||
Copyright (C) 1988-2002 Free Software Foundation, Inc.
|
||||
Authored by Brian Fox and Chet Ramey.
|
||||
|
||||
Permission is granted to make and distribute verbatim copies of this manual
|
||||
provided the copyright notice and this permission notice are preserved on
|
||||
all copies.
|
||||
|
||||
Permission is granted to process this file through Tex and print the
|
||||
results, provided the printed document carries copying permission notice
|
||||
identical to this one except for the removal of this paragraph (this
|
||||
paragraph not being relevant to the printed manual).
|
||||
|
||||
Permission is granted to copy and distribute modified versions of this
|
||||
manual under the conditions for verbatim copying, provided also that the
|
||||
GNU Copyright statement is available to the distributee, and provided that
|
||||
the entire resulting derived work is distributed under the terms of a
|
||||
permission notice identical to this one.
|
||||
|
||||
Permission is granted to copy and distribute translations of this manual
|
||||
into another language, under the above conditions for modified versions.
|
||||
@end ignore
|
||||
|
||||
@node Programming with GNU History
|
||||
@chapter Programming with GNU History
|
||||
|
||||
This chapter describes how to interface programs that you write
|
||||
with the @sc{gnu} History Library.
|
||||
It should be considered a technical guide.
|
||||
For information on the interactive use of @sc{gnu} History, @pxref{Using
|
||||
History Interactively}.
|
||||
|
||||
@menu
|
||||
* Introduction to History:: What is the GNU History library for?
|
||||
* History Storage:: How information is stored.
|
||||
* History Functions:: Functions that you can use.
|
||||
* History Variables:: Variables that control behaviour.
|
||||
* History Programming Example:: Example of using the GNU History Library.
|
||||
@end menu
|
||||
|
||||
@node Introduction to History
|
||||
@section Introduction to History
|
||||
|
||||
Many programs read input from the user a line at a time. The @sc{gnu}
|
||||
History library is able to keep track of those lines, associate arbitrary
|
||||
data with each line, and utilize information from previous lines in
|
||||
composing new ones.
|
||||
|
||||
The programmer using the History library has available functions
|
||||
for remembering lines on a history list, associating arbitrary data
|
||||
with a line, removing lines from the list, searching through the list
|
||||
for a line containing an arbitrary text string, and referencing any line
|
||||
in the list directly. In addition, a history @dfn{expansion} function
|
||||
is available which provides for a consistent user interface across
|
||||
different programs.
|
||||
|
||||
The user using programs written with the History library has the
|
||||
benefit of a consistent user interface with a set of well-known
|
||||
commands for manipulating the text of previous lines and using that text
|
||||
in new commands. The basic history manipulation commands are similar to
|
||||
the history substitution provided by @code{csh}.
|
||||
|
||||
If the programmer desires, he can use the Readline library, which
|
||||
includes some history manipulation by default, and has the added
|
||||
advantage of command line editing.
|
||||
|
||||
Before declaring any functions using any functionality the History
|
||||
library provides in other code, an application writer should include
|
||||
the file @code{<readline/history.h>} in any file that uses the
|
||||
History library's features. It supplies extern declarations for all
|
||||
of the library's public functions and variables, and declares all of
|
||||
the public data structures.
|
||||
|
||||
@node History Storage
|
||||
@section History Storage
|
||||
|
||||
The history list is an array of history entries. A history entry is
|
||||
declared as follows:
|
||||
|
||||
@example
|
||||
typedef void *histdata_t;
|
||||
|
||||
typedef struct _hist_entry @{
|
||||
char *line;
|
||||
char *timestamp;
|
||||
histdata_t data;
|
||||
@} HIST_ENTRY;
|
||||
@end example
|
||||
|
||||
The history list itself might therefore be declared as
|
||||
|
||||
@example
|
||||
HIST_ENTRY **the_history_list;
|
||||
@end example
|
||||
|
||||
The state of the History library is encapsulated into a single structure:
|
||||
|
||||
@example
|
||||
/*
|
||||
* A structure used to pass around the current state of the history.
|
||||
*/
|
||||
typedef struct _hist_state @{
|
||||
HIST_ENTRY **entries; /* Pointer to the entries themselves. */
|
||||
int offset; /* The location pointer within this array. */
|
||||
int length; /* Number of elements within this array. */
|
||||
int size; /* Number of slots allocated to this array. */
|
||||
int flags;
|
||||
@} HISTORY_STATE;
|
||||
@end example
|
||||
|
||||
If the flags member includes @code{HS_STIFLED}, the history has been
|
||||
stifled.
|
||||
|
||||
@node History Functions
|
||||
@section History Functions
|
||||
|
||||
This section describes the calling sequence for the various functions
|
||||
exported by the @sc{gnu} History library.
|
||||
|
||||
@menu
|
||||
* Initializing History and State Management:: Functions to call when you
|
||||
want to use history in a
|
||||
program.
|
||||
* History List Management:: Functions used to manage the list
|
||||
of history entries.
|
||||
* Information About the History List:: Functions returning information about
|
||||
the history list.
|
||||
* Moving Around the History List:: Functions used to change the position
|
||||
in the history list.
|
||||
* Searching the History List:: Functions to search the history list
|
||||
for entries containing a string.
|
||||
* Managing the History File:: Functions that read and write a file
|
||||
containing the history list.
|
||||
* History Expansion:: Functions to perform csh-like history
|
||||
expansion.
|
||||
@end menu
|
||||
|
||||
@node Initializing History and State Management
|
||||
@subsection Initializing History and State Management
|
||||
|
||||
This section describes functions used to initialize and manage
|
||||
the state of the History library when you want to use the history
|
||||
functions in your program.
|
||||
|
||||
@deftypefun void using_history (void)
|
||||
Begin a session in which the history functions might be used. This
|
||||
initializes the interactive variables.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun {HISTORY_STATE *} history_get_history_state (void)
|
||||
Return a structure describing the current state of the input history.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun void history_set_history_state (HISTORY_STATE *state)
|
||||
Set the state of the history list according to @var{state}.
|
||||
@end deftypefun
|
||||
|
||||
@node History List Management
|
||||
@subsection History List Management
|
||||
|
||||
These functions manage individual entries on the history list, or set
|
||||
parameters managing the list itself.
|
||||
|
||||
@deftypefun void add_history (const char *string)
|
||||
Place @var{string} at the end of the history list. The associated data
|
||||
field (if any) is set to @code{NULL}.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun void add_history_time (const char *string)
|
||||
Change the time stamp associated with the most recent history entry to
|
||||
@var{string}.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun {HIST_ENTRY *} remove_history (int which)
|
||||
Remove history entry at offset @var{which} from the history. The
|
||||
removed element is returned so you can free the line, data,
|
||||
and containing structure.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun {histdata_t} free_history_entry (HIST_ENTRY *histent)
|
||||
Free the history entry @var{histent} and any history library private
|
||||
data associated with it. Returns the application-specific data
|
||||
so the caller can dispose of it.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun {HIST_ENTRY *} replace_history_entry (int which, const char *line, histdata_t data)
|
||||
Make the history entry at offset @var{which} have @var{line} and @var{data}.
|
||||
This returns the old entry so the caller can dispose of any
|
||||
application-specific data. In the case
|
||||
of an invalid @var{which}, a @code{NULL} pointer is returned.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun void clear_history (void)
|
||||
Clear the history list by deleting all the entries.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun void stifle_history (int max)
|
||||
Stifle the history list, remembering only the last @var{max} entries.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun int unstifle_history (void)
|
||||
Stop stifling the history. This returns the previously-set
|
||||
maximum number of history entries (as set by @code{stifle_history()}).
|
||||
The value is positive if the history was
|
||||
stifled, negative if it wasn't.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun int history_is_stifled (void)
|
||||
Returns non-zero if the history is stifled, zero if it is not.
|
||||
@end deftypefun
|
||||
|
||||
@node Information About the History List
|
||||
@subsection Information About the History List
|
||||
|
||||
These functions return information about the entire history list or
|
||||
individual list entries.
|
||||
|
||||
@deftypefun {HIST_ENTRY **} history_list (void)
|
||||
Return a @code{NULL} terminated array of @code{HIST_ENTRY *} which is the
|
||||
current input history. Element 0 of this list is the beginning of time.
|
||||
If there is no history, return @code{NULL}.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun int where_history (void)
|
||||
Returns the offset of the current history element.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun {HIST_ENTRY *} current_history (void)
|
||||
Return the history entry at the current position, as determined by
|
||||
@code{where_history()}. If there is no entry there, return a @code{NULL}
|
||||
pointer.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun {HIST_ENTRY *} history_get (int offset)
|
||||
Return the history entry at position @var{offset}, starting from
|
||||
@code{history_base} (@pxref{History Variables}).
|
||||
If there is no entry there, or if @var{offset}
|
||||
is greater than the history length, return a @code{NULL} pointer.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun time_t history_get_time (HIST_ENTRY *entry)
|
||||
Return the time stamp associated with the history entry @var{entry}.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun int history_total_bytes (void)
|
||||
Return the number of bytes that the primary history entries are using.
|
||||
This function returns the sum of the lengths of all the lines in the
|
||||
history.
|
||||
@end deftypefun
|
||||
|
||||
@node Moving Around the History List
|
||||
@subsection Moving Around the History List
|
||||
|
||||
These functions allow the current index into the history list to be
|
||||
set or changed.
|
||||
|
||||
@deftypefun int history_set_pos (int pos)
|
||||
Set the current history offset to @var{pos}, an absolute index
|
||||
into the list.
|
||||
Returns 1 on success, 0 if @var{pos} is less than zero or greater
|
||||
than the number of history entries.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun {HIST_ENTRY *} previous_history (void)
|
||||
Back up the current history offset to the previous history entry, and
|
||||
return a pointer to that entry. If there is no previous entry, return
|
||||
a @code{NULL} pointer.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun {HIST_ENTRY *} next_history (void)
|
||||
Move the current history offset forward to the next history entry, and
|
||||
return the a pointer to that entry. If there is no next entry, return
|
||||
a @code{NULL} pointer.
|
||||
@end deftypefun
|
||||
|
||||
@node Searching the History List
|
||||
@subsection Searching the History List
|
||||
@cindex History Searching
|
||||
|
||||
These functions allow searching of the history list for entries containing
|
||||
a specific string. Searching may be performed both forward and backward
|
||||
from the current history position. The search may be @dfn{anchored},
|
||||
meaning that the string must match at the beginning of the history entry.
|
||||
@cindex anchored search
|
||||
|
||||
@deftypefun int history_search (const char *string, int direction)
|
||||
Search the history for @var{string}, starting at the current history offset.
|
||||
If @var{direction} is less than 0, then the search is through
|
||||
previous entries, otherwise through subsequent entries.
|
||||
If @var{string} is found, then
|
||||
the current history index is set to that history entry, and the value
|
||||
returned is the offset in the line of the entry where
|
||||
@var{string} was found. Otherwise, nothing is changed, and a -1 is
|
||||
returned.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun int history_search_prefix (const char *string, int direction)
|
||||
Search the history for @var{string}, starting at the current history
|
||||
offset. The search is anchored: matching lines must begin with
|
||||
@var{string}. If @var{direction} is less than 0, then the search is
|
||||
through previous entries, otherwise through subsequent entries.
|
||||
If @var{string} is found, then the
|
||||
current history index is set to that entry, and the return value is 0.
|
||||
Otherwise, nothing is changed, and a -1 is returned.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun int history_search_pos (const char *string, int direction, int pos)
|
||||
Search for @var{string} in the history list, starting at @var{pos}, an
|
||||
absolute index into the list. If @var{direction} is negative, the search
|
||||
proceeds backward from @var{pos}, otherwise forward. Returns the absolute
|
||||
index of the history element where @var{string} was found, or -1 otherwise.
|
||||
@end deftypefun
|
||||
|
||||
@node Managing the History File
|
||||
@subsection Managing the History File
|
||||
|
||||
The History library can read the history from and write it to a file.
|
||||
This section documents the functions for managing a history file.
|
||||
|
||||
@deftypefun int read_history (const char *filename)
|
||||
Add the contents of @var{filename} to the history list, a line at a time.
|
||||
If @var{filename} is @code{NULL}, then read from @file{~/.history}.
|
||||
Returns 0 if successful, or @code{errno} if not.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun int read_history_range (const char *filename, int from, int to)
|
||||
Read a range of lines from @var{filename}, adding them to the history list.
|
||||
Start reading at line @var{from} and end at @var{to}.
|
||||
If @var{from} is zero, start at the beginning. If @var{to} is less than
|
||||
@var{from}, then read until the end of the file. If @var{filename} is
|
||||
@code{NULL}, then read from @file{~/.history}. Returns 0 if successful,
|
||||
or @code{errno} if not.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun int write_history (const char *filename)
|
||||
Write the current history to @var{filename}, overwriting @var{filename}
|
||||
if necessary.
|
||||
If @var{filename} is @code{NULL}, then write the history list to
|
||||
@file{~/.history}.
|
||||
Returns 0 on success, or @code{errno} on a read or write error.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun int append_history (int nelements, const char *filename)
|
||||
Append the last @var{nelements} of the history list to @var{filename}.
|
||||
If @var{filename} is @code{NULL}, then append to @file{~/.history}.
|
||||
Returns 0 on success, or @code{errno} on a read or write error.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun int history_truncate_file (const char *filename, int nlines)
|
||||
Truncate the history file @var{filename}, leaving only the last
|
||||
@var{nlines} lines.
|
||||
If @var{filename} is @code{NULL}, then @file{~/.history} is truncated.
|
||||
Returns 0 on success, or @code{errno} on failure.
|
||||
@end deftypefun
|
||||
|
||||
@node History Expansion
|
||||
@subsection History Expansion
|
||||
|
||||
These functions implement history expansion.
|
||||
|
||||
@deftypefun int history_expand (char *string, char **output)
|
||||
Expand @var{string}, placing the result into @var{output}, a pointer
|
||||
to a string (@pxref{History Interaction}). Returns:
|
||||
@table @code
|
||||
@item 0
|
||||
If no expansions took place (or, if the only change in
|
||||
the text was the removal of escape characters preceding the history expansion
|
||||
character);
|
||||
@item 1
|
||||
if expansions did take place;
|
||||
@item -1
|
||||
if there was an error in expansion;
|
||||
@item 2
|
||||
if the returned line should be displayed, but not executed,
|
||||
as with the @code{:p} modifier (@pxref{Modifiers}).
|
||||
@end table
|
||||
|
||||
If an error ocurred in expansion, then @var{output} contains a descriptive
|
||||
error message.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun {char *} get_history_event (const char *string, int *cindex, int qchar)
|
||||
Returns the text of the history event beginning at @var{string} +
|
||||
@var{*cindex}. @var{*cindex} is modified to point to after the event
|
||||
specifier. At function entry, @var{cindex} points to the index into
|
||||
@var{string} where the history event specification begins. @var{qchar}
|
||||
is a character that is allowed to end the event specification in addition
|
||||
to the ``normal'' terminating characters.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun {char **} history_tokenize (const char *string)
|
||||
Return an array of tokens parsed out of @var{string}, much as the
|
||||
shell might. The tokens are split on the characters in the
|
||||
@var{history_word_delimiters} variable,
|
||||
and shell quoting conventions are obeyed.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun {char *} history_arg_extract (int first, int last, const char *string)
|
||||
Extract a string segment consisting of the @var{first} through @var{last}
|
||||
arguments present in @var{string}. Arguments are split using
|
||||
@code{history_tokenize}.
|
||||
@end deftypefun
|
||||
|
||||
@node History Variables
|
||||
@section History Variables
|
||||
|
||||
This section describes the externally-visible variables exported by
|
||||
the @sc{gnu} History Library.
|
||||
|
||||
@deftypevar int history_base
|
||||
The logical offset of the first entry in the history list.
|
||||
@end deftypevar
|
||||
|
||||
@deftypevar int history_length
|
||||
The number of entries currently stored in the history list.
|
||||
@end deftypevar
|
||||
|
||||
@deftypevar int history_max_entries
|
||||
The maximum number of history entries. This must be changed using
|
||||
@code{stifle_history()}.
|
||||
@end deftypevar
|
||||
|
||||
@deftypevar int history_write_timestamps
|
||||
If non-zero, timestamps are written to the history file, so they can be
|
||||
preserved between sessions. The default value is 0, meaning that
|
||||
timestamps are not saved.
|
||||
@end deftypevar
|
||||
|
||||
@deftypevar char history_expansion_char
|
||||
The character that introduces a history event. The default is @samp{!}.
|
||||
Setting this to 0 inhibits history expansion.
|
||||
@end deftypevar
|
||||
|
||||
@deftypevar char history_subst_char
|
||||
The character that invokes word substitution if found at the start of
|
||||
a line. The default is @samp{^}.
|
||||
@end deftypevar
|
||||
|
||||
@deftypevar char history_comment_char
|
||||
During tokenization, if this character is seen as the first character
|
||||
of a word, then it and all subsequent characters up to a newline are
|
||||
ignored, suppressing history expansion for the remainder of the line.
|
||||
This is disabled by default.
|
||||
@end deftypevar
|
||||
|
||||
@deftypevar {char *} history_word_delimiters
|
||||
The characters that separate tokens for @code{history_tokenize()}.
|
||||
The default value is @code{" \t\n()<>;&|"}.
|
||||
@end deftypevar
|
||||
|
||||
@deftypevar {char *} history_search_delimiter_chars
|
||||
The list of additional characters which can delimit a history search
|
||||
string, in addition to space, TAB, @samp{:} and @samp{?} in the case of
|
||||
a substring search. The default is empty.
|
||||
@end deftypevar
|
||||
|
||||
@deftypevar {char *} history_no_expand_chars
|
||||
The list of characters which inhibit history expansion if found immediately
|
||||
following @var{history_expansion_char}. The default is space, tab, newline,
|
||||
carriage return, and @samp{=}.
|
||||
@end deftypevar
|
||||
|
||||
@deftypevar int history_quotes_inhibit_expansion
|
||||
If non-zero, single-quoted words are not scanned for the history expansion
|
||||
character. The default value is 0.
|
||||
@end deftypevar
|
||||
|
||||
@deftypevar {rl_linebuf_func_t *} history_inhibit_expansion_function
|
||||
This should be set to the address of a function that takes two arguments:
|
||||
a @code{char *} (@var{string})
|
||||
and an @code{int} index into that string (@var{i}).
|
||||
It should return a non-zero value if the history expansion starting at
|
||||
@var{string[i]} should not be performed; zero if the expansion should
|
||||
be done.
|
||||
It is intended for use by applications like Bash that use the history
|
||||
expansion character for additional purposes.
|
||||
By default, this variable is set to @code{NULL}.
|
||||
@end deftypevar
|
||||
|
||||
@node History Programming Example
|
||||
@section History Programming Example
|
||||
|
||||
The following program demonstrates simple use of the @sc{gnu} History Library.
|
||||
|
||||
@smallexample
|
||||
#include <stdio.h>
|
||||
#include <readline/history.h>
|
||||
|
||||
main (argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
@{
|
||||
char line[1024], *t;
|
||||
int len, done = 0;
|
||||
|
||||
line[0] = 0;
|
||||
|
||||
using_history ();
|
||||
while (!done)
|
||||
@{
|
||||
printf ("history$ ");
|
||||
fflush (stdout);
|
||||
t = fgets (line, sizeof (line) - 1, stdin);
|
||||
if (t && *t)
|
||||
@{
|
||||
len = strlen (t);
|
||||
if (t[len - 1] == '\n')
|
||||
t[len - 1] = '\0';
|
||||
@}
|
||||
|
||||
if (!t)
|
||||
strcpy (line, "quit");
|
||||
|
||||
if (line[0])
|
||||
@{
|
||||
char *expansion;
|
||||
int result;
|
||||
|
||||
result = history_expand (line, &expansion);
|
||||
if (result)
|
||||
fprintf (stderr, "%s\n", expansion);
|
||||
|
||||
if (result < 0 || result == 2)
|
||||
@{
|
||||
free (expansion);
|
||||
continue;
|
||||
@}
|
||||
|
||||
add_history (expansion);
|
||||
strncpy (line, expansion, sizeof (line) - 1);
|
||||
free (expansion);
|
||||
@}
|
||||
|
||||
if (strcmp (line, "quit") == 0)
|
||||
done = 1;
|
||||
else if (strcmp (line, "save") == 0)
|
||||
write_history ("history_file");
|
||||
else if (strcmp (line, "read") == 0)
|
||||
read_history ("history_file");
|
||||
else if (strcmp (line, "list") == 0)
|
||||
@{
|
||||
register HIST_ENTRY **the_list;
|
||||
register int i;
|
||||
|
||||
the_list = history_list ();
|
||||
if (the_list)
|
||||
for (i = 0; the_list[i]; i++)
|
||||
printf ("%d: %s\n", i + history_base, the_list[i]->line);
|
||||
@}
|
||||
else if (strncmp (line, "delete", 6) == 0)
|
||||
@{
|
||||
int which;
|
||||
if ((sscanf (line + 6, "%d", &which)) == 1)
|
||||
@{
|
||||
HIST_ENTRY *entry = remove_history (which);
|
||||
if (!entry)
|
||||
fprintf (stderr, "No such entry %d\n", which);
|
||||
else
|
||||
@{
|
||||
free (entry->line);
|
||||
free (entry);
|
||||
@}
|
||||
@}
|
||||
else
|
||||
@{
|
||||
fprintf (stderr, "non-numeric arg given to `delete'\n");
|
||||
@}
|
||||
@}
|
||||
@}
|
||||
@}
|
||||
@end smallexample
|
||||
@@ -0,0 +1,457 @@
|
||||
@ignore
|
||||
This file documents the user interface to the GNU History library.
|
||||
|
||||
Copyright (C) 1988-2002 Free Software Foundation, Inc.
|
||||
Authored by Brian Fox and Chet Ramey.
|
||||
|
||||
Permission is granted to make and distribute verbatim copies of this manual
|
||||
provided the copyright notice and this permission notice are preserved on
|
||||
all copies.
|
||||
|
||||
Permission is granted to process this file through Tex and print the
|
||||
results, provided the printed document carries copying permission notice
|
||||
identical to this one except for the removal of this paragraph (this
|
||||
paragraph not being relevant to the printed manual).
|
||||
|
||||
Permission is granted to copy and distribute modified versions of this
|
||||
manual under the conditions for verbatim copying, provided also that the
|
||||
GNU Copyright statement is available to the distributee, and provided that
|
||||
the entire resulting derived work is distributed under the terms of a
|
||||
permission notice identical to this one.
|
||||
|
||||
Permission is granted to copy and distribute translations of this manual
|
||||
into another language, under the above conditions for modified versions.
|
||||
@end ignore
|
||||
|
||||
@node Using History Interactively
|
||||
@chapter Using History Interactively
|
||||
|
||||
@ifclear BashFeatures
|
||||
@defcodeindex bt
|
||||
@end ifclear
|
||||
|
||||
@ifset BashFeatures
|
||||
This chapter describes how to use the @sc{gnu} History Library
|
||||
interactively, from a user's standpoint.
|
||||
It should be considered a user's guide.
|
||||
For information on using the @sc{gnu} History Library in other programs,
|
||||
see the @sc{gnu} Readline Library Manual.
|
||||
@end ifset
|
||||
@ifclear BashFeatures
|
||||
This chapter describes how to use the @sc{gnu} History Library interactively,
|
||||
from a user's standpoint. It should be considered a user's guide. For
|
||||
information on using the @sc{gnu} History Library in your own programs,
|
||||
@pxref{Programming with GNU History}.
|
||||
@end ifclear
|
||||
|
||||
@ifset BashFeatures
|
||||
@menu
|
||||
* Bash History Facilities:: How Bash lets you manipulate your command
|
||||
history.
|
||||
* Bash History Builtins:: The Bash builtin commands that manipulate
|
||||
the command history.
|
||||
* History Interaction:: What it feels like using History as a user.
|
||||
@end menu
|
||||
@end ifset
|
||||
@ifclear BashFeatures
|
||||
@menu
|
||||
* History Interaction:: What it feels like using History as a user.
|
||||
@end menu
|
||||
@end ifclear
|
||||
|
||||
@ifset BashFeatures
|
||||
@node Bash History Facilities
|
||||
@section Bash History Facilities
|
||||
@cindex command history
|
||||
@cindex history list
|
||||
|
||||
When the @option{-o history} option to the @code{set} builtin
|
||||
is enabled (@pxref{The Set Builtin}),
|
||||
the shell provides access to the @dfn{command history},
|
||||
the list of commands previously typed.
|
||||
The value of the @env{HISTSIZE} shell variable is used as the
|
||||
number of commands to save in a history list.
|
||||
The text of the last @env{$HISTSIZE}
|
||||
commands (default 500) is saved.
|
||||
The shell stores each command in the history list prior to
|
||||
parameter and variable expansion
|
||||
but after history expansion is performed, subject to the
|
||||
values of the shell variables
|
||||
@env{HISTIGNORE} and @env{HISTCONTROL}.
|
||||
|
||||
When the shell starts up, the history is initialized from the
|
||||
file named by the @env{HISTFILE} variable (default @file{~/.bash_history}).
|
||||
The file named by the value of @env{HISTFILE} is truncated, if
|
||||
necessary, to contain no more than the number of lines specified by
|
||||
the value of the @env{HISTFILESIZE} variable.
|
||||
When an interactive shell exits, the last
|
||||
@env{$HISTSIZE} lines are copied from the history list to the file
|
||||
named by @env{$HISTFILE}.
|
||||
If the @code{histappend} shell option is set (@pxref{Bash Builtins}),
|
||||
the lines are appended to the history file,
|
||||
otherwise the history file is overwritten.
|
||||
If @env{HISTFILE}
|
||||
is unset, or if the history file is unwritable, the history is
|
||||
not saved. After saving the history, the history file is truncated
|
||||
to contain no more than @env{$HISTFILESIZE}
|
||||
lines. If @env{HISTFILESIZE} is not set, no truncation is performed.
|
||||
|
||||
If the @env{HISTTIMEFORMAT} is set, the time stamp information
|
||||
associated with each history entry is written to the history file.
|
||||
|
||||
The builtin command @code{fc} may be used to list or edit and re-execute
|
||||
a portion of the history list.
|
||||
The @code{history} builtin may be used to display or modify the history
|
||||
list and manipulate the history file.
|
||||
When using command-line editing, search commands
|
||||
are available in each editing mode that provide access to the
|
||||
history list (@pxref{Commands For History}).
|
||||
|
||||
The shell allows control over which commands are saved on the history
|
||||
list. The @env{HISTCONTROL} and @env{HISTIGNORE}
|
||||
variables may be set to cause the shell to save only a subset of the
|
||||
commands entered.
|
||||
The @code{cmdhist}
|
||||
shell option, if enabled, causes the shell to attempt to save each
|
||||
line of a multi-line command in the same history entry, adding
|
||||
semicolons where necessary to preserve syntactic correctness.
|
||||
The @code{lithist}
|
||||
shell option causes the shell to save the command with embedded newlines
|
||||
instead of semicolons.
|
||||
The @code{shopt} builtin is used to set these options.
|
||||
@xref{Bash Builtins}, for a description of @code{shopt}.
|
||||
|
||||
@node Bash History Builtins
|
||||
@section Bash History Builtins
|
||||
@cindex history builtins
|
||||
|
||||
Bash provides two builtin commands which manipulate the
|
||||
history list and history file.
|
||||
|
||||
@table @code
|
||||
|
||||
@item fc
|
||||
@btindex fc
|
||||
@example
|
||||
@code{fc [-e @var{ename}] [-nlr] [@var{first}] [@var{last}]}
|
||||
@code{fc -s [@var{pat}=@var{rep}] [@var{command}]}
|
||||
@end example
|
||||
|
||||
Fix Command. In the first form, a range of commands from @var{first} to
|
||||
@var{last} is selected from the history list. Both @var{first} and
|
||||
@var{last} may be specified as a string (to locate the most recent
|
||||
command beginning with that string) or as a number (an index into the
|
||||
history list, where a negative number is used as an offset from the
|
||||
current command number). If @var{last} is not specified it is set to
|
||||
@var{first}. If @var{first} is not specified it is set to the previous
|
||||
command for editing and @minus{}16 for listing. If the @option{-l} flag is
|
||||
given, the commands are listed on standard output. The @option{-n} flag
|
||||
suppresses the command numbers when listing. The @option{-r} flag
|
||||
reverses the order of the listing. Otherwise, the editor given by
|
||||
@var{ename} is invoked on a file containing those commands. If
|
||||
@var{ename} is not given, the value of the following variable expansion
|
||||
is used: @code{$@{FCEDIT:-$@{EDITOR:-vi@}@}}. This says to use the
|
||||
value of the @env{FCEDIT} variable if set, or the value of the
|
||||
@env{EDITOR} variable if that is set, or @code{vi} if neither is set.
|
||||
When editing is complete, the edited commands are echoed and executed.
|
||||
|
||||
In the second form, @var{command} is re-executed after each instance
|
||||
of @var{pat} in the selected command is replaced by @var{rep}.
|
||||
|
||||
A useful alias to use with the @code{fc} command is @code{r='fc -s'}, so
|
||||
that typing @samp{r cc} runs the last command beginning with @code{cc}
|
||||
and typing @samp{r} re-executes the last command (@pxref{Aliases}).
|
||||
|
||||
@item history
|
||||
@btindex history
|
||||
@example
|
||||
history [@var{n}]
|
||||
history -c
|
||||
history -d @var{offset}
|
||||
history [-anrw] [@var{filename}]
|
||||
history -ps @var{arg}
|
||||
@end example
|
||||
|
||||
With no options, display the history list with line numbers.
|
||||
Lines prefixed with a @samp{*} have been modified.
|
||||
An argument of @var{n} lists only the last @var{n} lines.
|
||||
If the shell variable @env{HISTTIMEFORMAT} is set and not null,
|
||||
it is used as a format string for @var{strftime} to display
|
||||
the time stamp associated with each displayed history entry.
|
||||
No intervening blank is printed between the formatted time stamp
|
||||
and the history line.
|
||||
|
||||
Options, if supplied, have the following meanings:
|
||||
|
||||
@table @code
|
||||
@item -c
|
||||
Clear the history list. This may be combined
|
||||
with the other options to replace the history list completely.
|
||||
|
||||
@item -d @var{offset}
|
||||
Delete the history entry at position @var{offset}.
|
||||
@var{offset} should be specified as it appears when the history is
|
||||
displayed.
|
||||
|
||||
@item -a
|
||||
Append the new
|
||||
history lines (history lines entered since the beginning of the
|
||||
current Bash session) to the history file.
|
||||
|
||||
@item -n
|
||||
Append the history lines not already read from the history file
|
||||
to the current history list. These are lines appended to the history
|
||||
file since the beginning of the current Bash session.
|
||||
|
||||
@item -r
|
||||
Read the current history file and append its contents to
|
||||
the history list.
|
||||
|
||||
@item -w
|
||||
Write out the current history to the history file.
|
||||
|
||||
@item -p
|
||||
Perform history substitution on the @var{arg}s and display the result
|
||||
on the standard output, without storing the results in the history list.
|
||||
|
||||
@item -s
|
||||
The @var{arg}s are added to the end of
|
||||
the history list as a single entry.
|
||||
|
||||
@end table
|
||||
|
||||
When any of the @option{-w}, @option{-r}, @option{-a}, or @option{-n} options is
|
||||
used, if @var{filename}
|
||||
is given, then it is used as the history file. If not, then
|
||||
the value of the @env{HISTFILE} variable is used.
|
||||
|
||||
@end table
|
||||
@end ifset
|
||||
|
||||
@node History Interaction
|
||||
@section History Expansion
|
||||
@cindex history expansion
|
||||
|
||||
The History library provides a history expansion feature that is similar
|
||||
to the history expansion provided by @code{csh}. This section
|
||||
describes the syntax used to manipulate the history information.
|
||||
|
||||
History expansions introduce words from the history list into
|
||||
the input stream, making it easy to repeat commands, insert the
|
||||
arguments to a previous command into the current input line, or
|
||||
fix errors in previous commands quickly.
|
||||
|
||||
History expansion takes place in two parts. The first is to determine
|
||||
which line from the history list should be used during substitution.
|
||||
The second is to select portions of that line for inclusion into the
|
||||
current one. The line selected from the history is called the
|
||||
@dfn{event}, and the portions of that line that are acted upon are
|
||||
called @dfn{words}. Various @dfn{modifiers} are available to manipulate
|
||||
the selected words. The line is broken into words in the same fashion
|
||||
that Bash does, so that several words
|
||||
surrounded by quotes are considered one word.
|
||||
History expansions are introduced by the appearance of the
|
||||
history expansion character, which is @samp{!} by default.
|
||||
@ifset BashFeatures
|
||||
Only @samp{\} and @samp{'} may be used to escape the history expansion
|
||||
character.
|
||||
@end ifset
|
||||
|
||||
@ifset BashFeatures
|
||||
Several shell options settable with the @code{shopt}
|
||||
builtin (@pxref{Bash Builtins}) may be used to tailor
|
||||
the behavior of history expansion. If the
|
||||
@code{histverify} shell option is enabled, and Readline
|
||||
is being used, history substitutions are not immediately passed to
|
||||
the shell parser.
|
||||
Instead, the expanded line is reloaded into the Readline
|
||||
editing buffer for further modification.
|
||||
If Readline is being used, and the @code{histreedit}
|
||||
shell option is enabled, a failed history expansion will be
|
||||
reloaded into the Readline editing buffer for correction.
|
||||
The @option{-p} option to the @code{history} builtin command
|
||||
may be used to see what a history expansion will do before using it.
|
||||
The @option{-s} option to the @code{history} builtin may be used to
|
||||
add commands to the end of the history list without actually executing
|
||||
them, so that they are available for subsequent recall.
|
||||
This is most useful in conjunction with Readline.
|
||||
|
||||
The shell allows control of the various characters used by the
|
||||
history expansion mechanism with the @code{histchars} variable.
|
||||
@end ifset
|
||||
|
||||
@menu
|
||||
* Event Designators:: How to specify which history line to use.
|
||||
* Word Designators:: Specifying which words are of interest.
|
||||
* Modifiers:: Modifying the results of substitution.
|
||||
@end menu
|
||||
|
||||
@node Event Designators
|
||||
@subsection Event Designators
|
||||
@cindex event designators
|
||||
|
||||
An event designator is a reference to a command line entry in the
|
||||
history list.
|
||||
@cindex history events
|
||||
|
||||
@table @asis
|
||||
|
||||
@item @code{!}
|
||||
@ifset BashFeatures
|
||||
Start a history substitution, except when followed by a space, tab,
|
||||
the end of the line, @samp{=} or @samp{(} (when the
|
||||
@code{extglob} shell option is enabled using the @code{shopt} builtin).
|
||||
@end ifset
|
||||
@ifclear BashFeatures
|
||||
Start a history substitution, except when followed by a space, tab,
|
||||
the end of the line, or @samp{=}.
|
||||
@end ifclear
|
||||
|
||||
@item @code{!@var{n}}
|
||||
Refer to command line @var{n}.
|
||||
|
||||
@item @code{!-@var{n}}
|
||||
Refer to the command @var{n} lines back.
|
||||
|
||||
@item @code{!!}
|
||||
Refer to the previous command. This is a synonym for @samp{!-1}.
|
||||
|
||||
@item @code{!@var{string}}
|
||||
Refer to the most recent command starting with @var{string}.
|
||||
|
||||
@item @code{!?@var{string}[?]}
|
||||
Refer to the most recent command containing @var{string}. The trailing
|
||||
@samp{?} may be omitted if the @var{string} is followed immediately by
|
||||
a newline.
|
||||
|
||||
@item @code{^@var{string1}^@var{string2}^}
|
||||
Quick Substitution. Repeat the last command, replacing @var{string1}
|
||||
with @var{string2}. Equivalent to
|
||||
@code{!!:s/@var{string1}/@var{string2}/}.
|
||||
|
||||
@item @code{!#}
|
||||
The entire command line typed so far.
|
||||
|
||||
@end table
|
||||
|
||||
@node Word Designators
|
||||
@subsection Word Designators
|
||||
|
||||
Word designators are used to select desired words from the event.
|
||||
A @samp{:} separates the event specification from the word designator. It
|
||||
may be omitted if the word designator begins with a @samp{^}, @samp{$},
|
||||
@samp{*}, @samp{-}, or @samp{%}. Words are numbered from the beginning
|
||||
of the line, with the first word being denoted by 0 (zero). Words are
|
||||
inserted into the current line separated by single spaces.
|
||||
|
||||
@need 0.75
|
||||
For example,
|
||||
|
||||
@table @code
|
||||
@item !!
|
||||
designates the preceding command. When you type this, the preceding
|
||||
command is repeated in toto.
|
||||
|
||||
@item !!:$
|
||||
designates the last argument of the preceding command. This may be
|
||||
shortened to @code{!$}.
|
||||
|
||||
@item !fi:2
|
||||
designates the second argument of the most recent command starting with
|
||||
the letters @code{fi}.
|
||||
@end table
|
||||
|
||||
@need 0.75
|
||||
Here are the word designators:
|
||||
|
||||
@table @code
|
||||
|
||||
@item 0 (zero)
|
||||
The @code{0}th word. For many applications, this is the command word.
|
||||
|
||||
@item @var{n}
|
||||
The @var{n}th word.
|
||||
|
||||
@item ^
|
||||
The first argument; that is, word 1.
|
||||
|
||||
@item $
|
||||
The last argument.
|
||||
|
||||
@item %
|
||||
The word matched by the most recent @samp{?@var{string}?} search.
|
||||
|
||||
@item @var{x}-@var{y}
|
||||
A range of words; @samp{-@var{y}} abbreviates @samp{0-@var{y}}.
|
||||
|
||||
@item *
|
||||
All of the words, except the @code{0}th. This is a synonym for @samp{1-$}.
|
||||
It is not an error to use @samp{*} if there is just one word in the event;
|
||||
the empty string is returned in that case.
|
||||
|
||||
@item @var{x}*
|
||||
Abbreviates @samp{@var{x}-$}
|
||||
|
||||
@item @var{x}-
|
||||
Abbreviates @samp{@var{x}-$} like @samp{@var{x}*}, but omits the last word.
|
||||
|
||||
@end table
|
||||
|
||||
If a word designator is supplied without an event specification, the
|
||||
previous command is used as the event.
|
||||
|
||||
@node Modifiers
|
||||
@subsection Modifiers
|
||||
|
||||
After the optional word designator, you can add a sequence of one or more
|
||||
of the following modifiers, each preceded by a @samp{:}.
|
||||
|
||||
@table @code
|
||||
|
||||
@item h
|
||||
Remove a trailing pathname component, leaving only the head.
|
||||
|
||||
@item t
|
||||
Remove all leading pathname components, leaving the tail.
|
||||
|
||||
@item r
|
||||
Remove a trailing suffix of the form @samp{.@var{suffix}}, leaving
|
||||
the basename.
|
||||
|
||||
@item e
|
||||
Remove all but the trailing suffix.
|
||||
|
||||
@item p
|
||||
Print the new command but do not execute it.
|
||||
|
||||
@ifset BashFeatures
|
||||
@item q
|
||||
Quote the substituted words, escaping further substitutions.
|
||||
|
||||
@item x
|
||||
Quote the substituted words as with @samp{q},
|
||||
but break into words at spaces, tabs, and newlines.
|
||||
@end ifset
|
||||
|
||||
@item s/@var{old}/@var{new}/
|
||||
Substitute @var{new} for the first occurrence of @var{old} in the
|
||||
event line. Any delimiter may be used in place of @samp{/}.
|
||||
The delimiter may be quoted in @var{old} and @var{new}
|
||||
with a single backslash. If @samp{&} appears in @var{new},
|
||||
it is replaced by @var{old}. A single backslash will quote
|
||||
the @samp{&}. The final delimiter is optional if it is the last
|
||||
character on the input line.
|
||||
|
||||
@item &
|
||||
Repeat the previous substitution.
|
||||
|
||||
@item g
|
||||
@itemx a
|
||||
Cause changes to be applied over the entire event line. Used in
|
||||
conjunction with @samp{s}, as in @code{gs/@var{old}/@var{new}/},
|
||||
or with @samp{&}.
|
||||
|
||||
@item G
|
||||
Apply the following @samp{s} modifier once to each word in the event.
|
||||
|
||||
@end table
|
||||
@@ -0,0 +1,101 @@
|
||||
\input texinfo @c -*-texinfo-*-
|
||||
@comment %**start of header (This is for running Texinfo on a region.)
|
||||
@setfilename readline.info
|
||||
@settitle GNU Readline Library
|
||||
@comment %**end of header (This is for running Texinfo on a region.)
|
||||
@synindex vr fn
|
||||
@setchapternewpage odd
|
||||
|
||||
@include version.texi
|
||||
|
||||
@copying
|
||||
This manual describes the GNU Readline Library
|
||||
(version @value{VERSION}, @value{UPDATED}), a library which aids in the
|
||||
consistency of user interface across discrete programs which provide
|
||||
a command line interface.
|
||||
|
||||
Copyright @copyright{} 1988-2003 Free Software Foundation, Inc.
|
||||
|
||||
Permission is granted to make and distribute verbatim copies of
|
||||
this manual provided the copyright notice and this permission notice
|
||||
are preserved on all copies.
|
||||
|
||||
@quotation
|
||||
Permission is granted to copy, distribute and/or modify this document
|
||||
under the terms of the GNU Free Documentation License, Version 1.1 or
|
||||
any later version published by the Free Software Foundation; with no
|
||||
Invariant Sections, with the Front-Cover texts being ``A GNU Manual,''
|
||||
and with the Back-Cover Texts as in (a) below. A copy of the license is
|
||||
included in the section entitled ``GNU Free Documentation License.''
|
||||
|
||||
(a) The FSF's Back-Cover Text is: ``You have freedom to copy and modify
|
||||
this GNU Manual, like GNU software. Copies published by the Free
|
||||
Software Foundation raise funds for GNU development.''
|
||||
@end quotation
|
||||
@end copying
|
||||
|
||||
@dircategory Libraries
|
||||
@direntry
|
||||
* Readline: (readline). The GNU readline library API.
|
||||
@end direntry
|
||||
|
||||
@titlepage
|
||||
@title GNU Readline Library
|
||||
@subtitle Edition @value{EDITION}, for @code{Readline Library} Version @value{VERSION}.
|
||||
@subtitle @value{UPDATED-MONTH}
|
||||
@author Chet Ramey, Case Western Reserve University
|
||||
@author Brian Fox, Free Software Foundation
|
||||
|
||||
@page
|
||||
@vskip 0pt plus 1filll
|
||||
@insertcopying
|
||||
|
||||
@sp 1
|
||||
Published by the Free Software Foundation @*
|
||||
59 Temple Place, Suite 330, @*
|
||||
Boston, MA 02111-1307 @*
|
||||
USA @*
|
||||
|
||||
@end titlepage
|
||||
|
||||
@contents
|
||||
|
||||
@ifnottex
|
||||
@node Top
|
||||
@top GNU Readline Library
|
||||
|
||||
This document describes the GNU Readline Library, a utility which aids
|
||||
in the consistency of user interface across discrete programs which
|
||||
provide a command line interface.
|
||||
|
||||
@menu
|
||||
* Command Line Editing:: GNU Readline User's Manual.
|
||||
* Programming with GNU Readline:: GNU Readline Programmer's Manual.
|
||||
* Copying This Manual:: Copying this manual.
|
||||
* Concept Index:: Index of concepts described in this manual.
|
||||
* Function and Variable Index:: Index of externally visible functions
|
||||
and variables.
|
||||
@end menu
|
||||
@end ifnottex
|
||||
|
||||
@include rluser.texi
|
||||
@include rltech.texi
|
||||
|
||||
@node Copying This Manual
|
||||
@appendix Copying This Manual
|
||||
|
||||
@menu
|
||||
* GNU Free Documentation License:: License for copying this manual.
|
||||
@end menu
|
||||
|
||||
@include fdl.texi
|
||||
|
||||
@node Concept Index
|
||||
@unnumbered Concept Index
|
||||
@printindex cp
|
||||
|
||||
@node Function and Variable Index
|
||||
@unnumbered Function and Variable Index
|
||||
@printindex fn
|
||||
|
||||
@bye
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,88 @@
|
||||
\input texinfo @c -*-texinfo-*-
|
||||
@comment %**start of header (This is for running Texinfo on a region.)
|
||||
@setfilename rluserman.info
|
||||
@settitle GNU Readline Library
|
||||
@comment %**end of header (This is for running Texinfo on a region.)
|
||||
|
||||
@setchapternewpage odd
|
||||
|
||||
@include version.texi
|
||||
|
||||
@copying
|
||||
This manual describes the end user interface of the GNU Readline Library
|
||||
(version @value{VERSION}, @value{UPDATED}), a library which aids in the
|
||||
consistency of user interface across discrete programs which provide
|
||||
a command line interface.
|
||||
|
||||
Copyright @copyright{} 1988-2003 Free Software Foundation, Inc.
|
||||
|
||||
Permission is granted to make and distribute verbatim copies of
|
||||
this manual provided the copyright notice and this permission notice
|
||||
are preserved on all copies.
|
||||
|
||||
@quotation
|
||||
Permission is granted to copy, distribute and/or modify this document
|
||||
under the terms of the GNU Free Documentation License, Version 1.1 or
|
||||
any later version published by the Free Software Foundation; with no
|
||||
Invariant Sections, with the Front-Cover texts being ``A GNU Manual,''
|
||||
and with the Back-Cover Texts as in (a) below. A copy of the license is
|
||||
included in the section entitled ``GNU Free Documentation License.''
|
||||
|
||||
(a) The FSF's Back-Cover Text is: ``You have freedom to copy and modify
|
||||
this GNU Manual, like GNU software. Copies published by the Free
|
||||
Software Foundation raise funds for GNU development.''
|
||||
@end quotation
|
||||
@end copying
|
||||
|
||||
@dircategory Libraries
|
||||
@direntry
|
||||
* RLuserman: (rluserman). The GNU readline library User's Manual.
|
||||
@end direntry
|
||||
|
||||
@titlepage
|
||||
@title GNU Readline Library User Interface
|
||||
@subtitle Edition @value{EDITION}, for @code{Readline Library} Version @value{VERSION}.
|
||||
@subtitle @value{UPDATED-MONTH}
|
||||
@author Chet Ramey, Case Western Reserve University
|
||||
@author Brian Fox, Free Software Foundation
|
||||
|
||||
@page
|
||||
@vskip 0pt plus 1filll
|
||||
@insertcopying
|
||||
|
||||
@sp 1
|
||||
Published by the Free Software Foundation @*
|
||||
59 Temple Place, Suite 330, @*
|
||||
Boston, MA 02111-1307 @*
|
||||
USA @*
|
||||
|
||||
@end titlepage
|
||||
|
||||
@contents
|
||||
|
||||
@ifnottex
|
||||
@node Top
|
||||
@top GNU Readline Library
|
||||
|
||||
This document describes the end user interface of the GNU Readline Library,
|
||||
a utility which aids in the consistency of user interface across discrete
|
||||
programs which provide a command line interface.
|
||||
|
||||
@menu
|
||||
* Command Line Editing:: GNU Readline User's Manual.
|
||||
* Copying This Manual:: Copying This Manual.
|
||||
@end menu
|
||||
@end ifnottex
|
||||
|
||||
@include rluser.texi
|
||||
|
||||
@node Copying This Manual
|
||||
@appendix Copying This Manual
|
||||
|
||||
@menu
|
||||
* GNU Free Documentation License:: License for copying this manual.
|
||||
@end menu
|
||||
|
||||
@include fdl.texi
|
||||
|
||||
@bye
|
||||
@@ -0,0 +1,10 @@
|
||||
@ignore
|
||||
Copyright (C) 1988-2003 Free Software Foundation, Inc.
|
||||
@end ignore
|
||||
|
||||
@set EDITION 5.0
|
||||
@set VERSION 5.0
|
||||
@set UPDATED 19 September 2003
|
||||
@set UPDATED-MONTH September 2003
|
||||
|
||||
@set LASTCHANGE Thu Sep 18 09:55:25 EDT 2003
|
||||
@@ -31,9 +31,10 @@ main (argc, argv)
|
||||
char **argv;
|
||||
{
|
||||
char line[1024], *t;
|
||||
int len, done = 0;
|
||||
int len, done;
|
||||
|
||||
line[0] = 0;
|
||||
done = 0;
|
||||
|
||||
using_history ();
|
||||
while (!done)
|
||||
@@ -42,71 +43,80 @@ main (argc, argv)
|
||||
fflush (stdout);
|
||||
t = fgets (line, sizeof (line) - 1, stdin);
|
||||
if (t && *t)
|
||||
{
|
||||
len = strlen (t);
|
||||
if (t[len - 1] == '\n')
|
||||
t[len - 1] = '\0';
|
||||
}
|
||||
{
|
||||
len = strlen (t);
|
||||
if (t[len - 1] == '\n')
|
||||
t[len - 1] = '\0';
|
||||
}
|
||||
|
||||
if (!t)
|
||||
strcpy (line, "quit");
|
||||
strcpy (line, "quit");
|
||||
|
||||
if (line[0])
|
||||
{
|
||||
char *expansion;
|
||||
int result;
|
||||
{
|
||||
char *expansion;
|
||||
int result;
|
||||
|
||||
using_history ();
|
||||
using_history ();
|
||||
|
||||
result = history_expand (line, &expansion);
|
||||
if (result)
|
||||
fprintf (stderr, "%s\n", expansion);
|
||||
result = history_expand (line, &expansion);
|
||||
if (result)
|
||||
fprintf (stderr, "%s\n", expansion);
|
||||
|
||||
if (result < 0 || result == 2)
|
||||
{
|
||||
free (expansion);
|
||||
continue;
|
||||
}
|
||||
if (result < 0 || result == 2)
|
||||
{
|
||||
free (expansion);
|
||||
continue;
|
||||
}
|
||||
|
||||
add_history (expansion);
|
||||
strncpy (line, expansion, sizeof (line) - 1);
|
||||
free (expansion);
|
||||
}
|
||||
add_history (expansion);
|
||||
strncpy (line, expansion, sizeof (line) - 1);
|
||||
free (expansion);
|
||||
}
|
||||
|
||||
if (strcmp (line, "quit") == 0)
|
||||
done = 1;
|
||||
done = 1;
|
||||
else if (strcmp (line, "save") == 0)
|
||||
write_history ("history_file");
|
||||
write_history ("history_file");
|
||||
else if (strcmp (line, "read") == 0)
|
||||
read_history ("history_file");
|
||||
read_history ("history_file");
|
||||
else if (strcmp (line, "list") == 0)
|
||||
{
|
||||
register HIST_ENTRY **the_list;
|
||||
register int i;
|
||||
{
|
||||
register HIST_ENTRY **the_list;
|
||||
register int i;
|
||||
time_t tt;
|
||||
char timestr[128];
|
||||
|
||||
the_list = history_list ();
|
||||
if (the_list)
|
||||
for (i = 0; the_list[i]; i++)
|
||||
printf ("%d: %s\n", i + history_base, the_list[i]->line);
|
||||
}
|
||||
the_list = history_list ();
|
||||
if (the_list)
|
||||
for (i = 0; the_list[i]; i++)
|
||||
{
|
||||
tt = history_get_time (the_list[i]);
|
||||
if (tt)
|
||||
strftime (timestr, sizeof (timestr), "%a %R", localtime(&tt));
|
||||
else
|
||||
strcpy (timestr, "??");
|
||||
printf ("%d: %s: %s\n", i + history_base, timestr, the_list[i]->line);
|
||||
}
|
||||
}
|
||||
else if (strncmp (line, "delete", 6) == 0)
|
||||
{
|
||||
int which;
|
||||
if ((sscanf (line + 6, "%d", &which)) == 1)
|
||||
{
|
||||
HIST_ENTRY *entry = remove_history (which);
|
||||
if (!entry)
|
||||
fprintf (stderr, "No such entry %d\n", which);
|
||||
else
|
||||
{
|
||||
free (entry->line);
|
||||
free (entry);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf (stderr, "non-numeric arg given to `delete'\n");
|
||||
}
|
||||
}
|
||||
{
|
||||
int which;
|
||||
if ((sscanf (line + 6, "%d", &which)) == 1)
|
||||
{
|
||||
HIST_ENTRY *entry = remove_history (which);
|
||||
if (!entry)
|
||||
fprintf (stderr, "No such entry %d\n", which);
|
||||
else
|
||||
{
|
||||
free (entry->line);
|
||||
free (entry);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf (stderr, "non-numeric arg given to `delete'\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+198
-114
@@ -52,6 +52,8 @@
|
||||
#define HISTORY_WORD_DELIMITERS " \t\n;&()|<>"
|
||||
#define HISTORY_QUOTE_CHARACTERS "\"'`"
|
||||
|
||||
#define slashify_in_quotes "\\`\"$"
|
||||
|
||||
typedef int _hist_search_func_t PARAMS((const char *, int));
|
||||
|
||||
extern int rl_byte_oriented; /* declared in mbutil.c */
|
||||
@@ -65,6 +67,8 @@ static int subst_rhs_len;
|
||||
|
||||
static char *get_history_word_specifier PARAMS((char *, char *, int *));
|
||||
static char *history_find_word PARAMS((char *, int));
|
||||
static int history_tokenize_word PARAMS((const char *, int));
|
||||
static char *history_substring PARAMS((const char *, int, int));
|
||||
|
||||
static char *quote_breaks PARAMS((char *));
|
||||
|
||||
@@ -211,8 +215,8 @@ get_history_event (string, caller_index, delimiting_quote)
|
||||
memset (&ps, 0, sizeof (mbstate_t));
|
||||
/* These produce warnings because we're passing a const string to a
|
||||
function that takes a non-const string. */
|
||||
_rl_adjust_point (string, i, &ps);
|
||||
if ((v = _rl_get_char_len (string + i, &ps)) > 1)
|
||||
_rl_adjust_point ((char *)string, i, &ps);
|
||||
if ((v = _rl_get_char_len ((char *)string + i, &ps)) > 1)
|
||||
{
|
||||
i += v - 1;
|
||||
continue;
|
||||
@@ -517,7 +521,7 @@ history_expand_internal (string, start, end_index_ptr, ret_string, current_line)
|
||||
char *current_line; /* for !# */
|
||||
{
|
||||
int i, n, starting_index;
|
||||
int substitute_globally, want_quotes, print_only;
|
||||
int substitute_globally, subst_bywords, want_quotes, print_only;
|
||||
char *event, *temp, *result, *tstr, *t, c, *word_spec;
|
||||
int result_len;
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
@@ -599,19 +603,25 @@ history_expand_internal (string, start, end_index_ptr, ret_string, current_line)
|
||||
FREE (word_spec);
|
||||
|
||||
/* Perhaps there are other modifiers involved. Do what they say. */
|
||||
want_quotes = substitute_globally = print_only = 0;
|
||||
want_quotes = substitute_globally = subst_bywords = print_only = 0;
|
||||
starting_index = i;
|
||||
|
||||
while (string[i] == ':')
|
||||
{
|
||||
c = string[i + 1];
|
||||
|
||||
if (c == 'g')
|
||||
if (c == 'g' || c == 'a')
|
||||
{
|
||||
substitute_globally = 1;
|
||||
i++;
|
||||
c = string[i + 1];
|
||||
}
|
||||
else if (c == 'G')
|
||||
{
|
||||
subst_bywords = 1;
|
||||
i++;
|
||||
c = string[i + 1];
|
||||
}
|
||||
|
||||
switch (c)
|
||||
{
|
||||
@@ -683,7 +693,7 @@ history_expand_internal (string, start, end_index_ptr, ret_string, current_line)
|
||||
case 's':
|
||||
{
|
||||
char *new_event;
|
||||
int delimiter, failed, si, l_temp;
|
||||
int delimiter, failed, si, l_temp, ws, we;
|
||||
|
||||
if (c == 's')
|
||||
{
|
||||
@@ -760,33 +770,67 @@ history_expand_internal (string, start, end_index_ptr, ret_string, current_line)
|
||||
}
|
||||
|
||||
/* Find the first occurrence of THIS in TEMP. */
|
||||
si = 0;
|
||||
/* Substitute SUBST_RHS for SUBST_LHS in TEMP. There are three
|
||||
cases to consider:
|
||||
|
||||
1. substitute_globally == subst_bywords == 0
|
||||
2. substitute_globally == 1 && subst_bywords == 0
|
||||
3. substitute_globally == 0 && subst_bywords == 1
|
||||
|
||||
In the first case, we substitute for the first occurrence only.
|
||||
In the second case, we substitute for every occurrence.
|
||||
In the third case, we tokenize into words and substitute the
|
||||
first occurrence of each word. */
|
||||
|
||||
si = we = 0;
|
||||
for (failed = 1; (si + subst_lhs_len) <= l_temp; si++)
|
||||
if (STREQN (temp+si, subst_lhs, subst_lhs_len))
|
||||
{
|
||||
int len = subst_rhs_len - subst_lhs_len + l_temp;
|
||||
new_event = (char *)xmalloc (1 + len);
|
||||
strncpy (new_event, temp, si);
|
||||
strncpy (new_event + si, subst_rhs, subst_rhs_len);
|
||||
strncpy (new_event + si + subst_rhs_len,
|
||||
temp + si + subst_lhs_len,
|
||||
l_temp - (si + subst_lhs_len));
|
||||
new_event[len] = '\0';
|
||||
free (temp);
|
||||
temp = new_event;
|
||||
{
|
||||
/* First skip whitespace and find word boundaries if
|
||||
we're past the end of the word boundary we found
|
||||
the last time. */
|
||||
if (subst_bywords && si > we)
|
||||
{
|
||||
for (; temp[si] && whitespace (temp[si]); si++)
|
||||
;
|
||||
ws = si;
|
||||
we = history_tokenize_word (temp, si);
|
||||
}
|
||||
|
||||
failed = 0;
|
||||
if (STREQN (temp+si, subst_lhs, subst_lhs_len))
|
||||
{
|
||||
int len = subst_rhs_len - subst_lhs_len + l_temp;
|
||||
new_event = (char *)xmalloc (1 + len);
|
||||
strncpy (new_event, temp, si);
|
||||
strncpy (new_event + si, subst_rhs, subst_rhs_len);
|
||||
strncpy (new_event + si + subst_rhs_len,
|
||||
temp + si + subst_lhs_len,
|
||||
l_temp - (si + subst_lhs_len));
|
||||
new_event[len] = '\0';
|
||||
free (temp);
|
||||
temp = new_event;
|
||||
|
||||
if (substitute_globally)
|
||||
{
|
||||
si += subst_rhs_len;
|
||||
l_temp = strlen (temp);
|
||||
substitute_globally++;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
failed = 0;
|
||||
|
||||
if (substitute_globally)
|
||||
{
|
||||
/* Reported to fix a bug that causes it to skip every
|
||||
other match when matching a single character. Was
|
||||
si += subst_rhs_len previously. */
|
||||
si += subst_rhs_len - 1;
|
||||
l_temp = strlen (temp);
|
||||
substitute_globally++;
|
||||
continue;
|
||||
}
|
||||
else if (subst_bywords)
|
||||
{
|
||||
si = we;
|
||||
l_temp = strlen (temp);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (substitute_globally > 1)
|
||||
{
|
||||
@@ -879,7 +923,7 @@ history_expand (hstring, output)
|
||||
char **output;
|
||||
{
|
||||
register int j;
|
||||
int i, r, l, passc, cc, modified, eindex, only_printing;
|
||||
int i, r, l, passc, cc, modified, eindex, only_printing, dquote;
|
||||
char *string;
|
||||
|
||||
/* The output string, and its length. */
|
||||
@@ -942,7 +986,7 @@ history_expand (hstring, output)
|
||||
|
||||
/* `!' followed by one of the characters in history_no_expand_chars
|
||||
is NOT an expansion. */
|
||||
for (i = 0; string[i]; i++)
|
||||
for (i = dquote = 0; string[i]; i++)
|
||||
{
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
|
||||
@@ -984,9 +1028,19 @@ history_expand (hstring, output)
|
||||
else
|
||||
break;
|
||||
}
|
||||
/* XXX - at some point, might want to extend this to handle
|
||||
double quotes as well. */
|
||||
else if (history_quotes_inhibit_expansion && string[i] == '\'')
|
||||
/* Shell-like quoting: allow backslashes to quote double quotes
|
||||
inside a double-quoted string. */
|
||||
else if (dquote && string[i] == '\\' && cc == '"')
|
||||
i++;
|
||||
/* More shell-like quoting: if we're paying attention to single
|
||||
quotes and letting them quote the history expansion character,
|
||||
then we need to pay attention to double quotes, because single
|
||||
quotes are not special inside double-quoted strings. */
|
||||
else if (history_quotes_inhibit_expansion && string[i] == '"')
|
||||
{
|
||||
dquote = 1 - dquote;
|
||||
}
|
||||
else if (dquote == 0 && history_quotes_inhibit_expansion && string[i] == '\'')
|
||||
{
|
||||
/* If this is bash, single quotes inhibit history expansion. */
|
||||
i++;
|
||||
@@ -999,6 +1053,7 @@ history_expand (hstring, output)
|
||||
if (cc == '\'' || cc == history_expansion_char)
|
||||
i++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (string[i] != history_expansion_char)
|
||||
@@ -1010,7 +1065,7 @@ history_expand (hstring, output)
|
||||
}
|
||||
|
||||
/* Extract and perform the substitution. */
|
||||
for (passc = i = j = 0; i < l; i++)
|
||||
for (passc = dquote = i = j = 0; i < l; i++)
|
||||
{
|
||||
int tchar = string[i];
|
||||
|
||||
@@ -1061,11 +1116,16 @@ history_expand (hstring, output)
|
||||
ADD_CHAR (tchar);
|
||||
break;
|
||||
|
||||
case '"':
|
||||
dquote = 1 - dquote;
|
||||
ADD_CHAR (tchar);
|
||||
break;
|
||||
|
||||
case '\'':
|
||||
{
|
||||
/* If history_quotes_inhibit_expansion is set, single quotes
|
||||
inhibit history expansion. */
|
||||
if (history_quotes_inhibit_expansion)
|
||||
if (dquote == 0 && history_quotes_inhibit_expansion)
|
||||
{
|
||||
int quote, slen;
|
||||
|
||||
@@ -1338,7 +1398,103 @@ history_arg_extract (first, last, string)
|
||||
return (result);
|
||||
}
|
||||
|
||||
#define slashify_in_quotes "\\`\"$"
|
||||
static int
|
||||
history_tokenize_word (string, ind)
|
||||
const char *string;
|
||||
int ind;
|
||||
{
|
||||
register int i;
|
||||
int delimiter;
|
||||
|
||||
i = ind;
|
||||
delimiter = 0;
|
||||
|
||||
if (member (string[i], "()\n"))
|
||||
{
|
||||
i++;
|
||||
return i;
|
||||
}
|
||||
|
||||
if (member (string[i], "<>;&|$"))
|
||||
{
|
||||
int peek = string[i + 1];
|
||||
|
||||
if (peek == string[i] && peek != '$')
|
||||
{
|
||||
if (peek == '<' && string[i + 2] == '-')
|
||||
i++;
|
||||
i += 2;
|
||||
return i;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((peek == '&' && (string[i] == '>' || string[i] == '<')) ||
|
||||
(peek == '>' && string[i] == '&') ||
|
||||
(peek == '(' && (string[i] == '>' || string[i] == '<')) || /* ) */
|
||||
(peek == '(' && string[i] == '$')) /* ) */
|
||||
{
|
||||
i += 2;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
if (string[i] != '$')
|
||||
{
|
||||
i++;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get word from string + i; */
|
||||
|
||||
if (member (string[i], HISTORY_QUOTE_CHARACTERS))
|
||||
delimiter = string[i++];
|
||||
|
||||
for (; string[i]; i++)
|
||||
{
|
||||
if (string[i] == '\\' && string[i + 1] == '\n')
|
||||
{
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (string[i] == '\\' && delimiter != '\'' &&
|
||||
(delimiter != '"' || member (string[i], slashify_in_quotes)))
|
||||
{
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (delimiter && string[i] == delimiter)
|
||||
{
|
||||
delimiter = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!delimiter && (member (string[i], history_word_delimiters)))
|
||||
break;
|
||||
|
||||
if (!delimiter && member (string[i], HISTORY_QUOTE_CHARACTERS))
|
||||
delimiter = string[i];
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
static char *
|
||||
history_substring (string, start, end)
|
||||
const char *string;
|
||||
int start, end;
|
||||
{
|
||||
register int len;
|
||||
register char *result;
|
||||
|
||||
len = end - start;
|
||||
result = (char *)xmalloc (len + 1);
|
||||
strncpy (result, string + start, len);
|
||||
result[len] = '\0';
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Parse STRING into tokens and return an array of strings. If WIND is
|
||||
not -1 and INDP is not null, we also want the word surrounding index
|
||||
@@ -1351,7 +1507,6 @@ history_tokenize_internal (string, wind, indp)
|
||||
{
|
||||
char **result;
|
||||
register int i, start, result_index, size;
|
||||
int len, delimiter;
|
||||
|
||||
/* If we're searching for a string that's not part of a word (e.g., " "),
|
||||
make sure we set *INDP to a reasonable value. */
|
||||
@@ -1362,8 +1517,6 @@ history_tokenize_internal (string, wind, indp)
|
||||
exactly where the shell would split them. */
|
||||
for (i = result_index = size = 0, result = (char **)NULL; string[i]; )
|
||||
{
|
||||
delimiter = 0;
|
||||
|
||||
/* Skip leading whitespace. */
|
||||
for (; string[i] && whitespace (string[i]); i++)
|
||||
;
|
||||
@@ -1371,88 +1524,19 @@ history_tokenize_internal (string, wind, indp)
|
||||
return (result);
|
||||
|
||||
start = i;
|
||||
|
||||
if (member (string[i], "()\n"))
|
||||
{
|
||||
i++;
|
||||
goto got_token;
|
||||
}
|
||||
|
||||
if (member (string[i], "<>;&|$"))
|
||||
{
|
||||
int peek = string[i + 1];
|
||||
|
||||
if (peek == string[i] && peek != '$')
|
||||
{
|
||||
if (peek == '<' && string[i + 2] == '-')
|
||||
i++;
|
||||
i += 2;
|
||||
goto got_token;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((peek == '&' && (string[i] == '>' || string[i] == '<')) ||
|
||||
((peek == '>') && (string[i] == '&')) ||
|
||||
((peek == '(') && (string[i] == '$')))
|
||||
{
|
||||
i += 2;
|
||||
goto got_token;
|
||||
}
|
||||
}
|
||||
if (string[i] != '$')
|
||||
{
|
||||
i++;
|
||||
goto got_token;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get word from string + i; */
|
||||
|
||||
if (member (string[i], HISTORY_QUOTE_CHARACTERS))
|
||||
delimiter = string[i++];
|
||||
|
||||
for (; string[i]; i++)
|
||||
{
|
||||
if (string[i] == '\\' && string[i + 1] == '\n')
|
||||
{
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (string[i] == '\\' && delimiter != '\'' &&
|
||||
(delimiter != '"' || member (string[i], slashify_in_quotes)))
|
||||
{
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (delimiter && string[i] == delimiter)
|
||||
{
|
||||
delimiter = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!delimiter && (member (string[i], history_word_delimiters)))
|
||||
break;
|
||||
|
||||
if (!delimiter && member (string[i], HISTORY_QUOTE_CHARACTERS))
|
||||
delimiter = string[i];
|
||||
}
|
||||
|
||||
got_token:
|
||||
i = history_tokenize_word (string, start);
|
||||
|
||||
/* If we are looking for the word in which the character at a
|
||||
particular index falls, remember it. */
|
||||
if (indp && wind != -1 && wind >= start && wind < i)
|
||||
*indp = result_index;
|
||||
|
||||
len = i - start;
|
||||
if (result_index + 2 >= size)
|
||||
result = (char **)xrealloc (result, ((size += 10) * sizeof (char *)));
|
||||
result[result_index] = (char *)xmalloc (1 + len);
|
||||
strncpy (result[result_index], string + start, len);
|
||||
result[result_index][len] = '\0';
|
||||
result[++result_index] = (char *)NULL;
|
||||
|
||||
result[result_index++] = history_substring (string, start, i);
|
||||
result[result_index] = (char *)NULL;
|
||||
}
|
||||
|
||||
return (result);
|
||||
|
||||
+93
-35
@@ -1,6 +1,6 @@
|
||||
/* histfile.c - functions to manipulate the history file. */
|
||||
|
||||
/* Copyright (C) 1989, 1992 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1989-2003 Free Software Foundation, Inc.
|
||||
|
||||
This file contains the GNU History Library (the Library), a set of
|
||||
routines for managing the text of previously typed lines.
|
||||
@@ -32,7 +32,7 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#ifndef _MINIX
|
||||
#if ! defined (_MINIX) && defined (HAVE_SYS_FILE_H)
|
||||
# include <sys/file.h>
|
||||
#endif
|
||||
#include "posixstat.h"
|
||||
@@ -52,7 +52,7 @@
|
||||
# undef HAVE_MMAP
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_MMAP
|
||||
#ifdef HISTORY_USE_MMAP
|
||||
# include <sys/mman.h>
|
||||
|
||||
# ifdef MAP_FILE
|
||||
@@ -67,7 +67,7 @@
|
||||
# define MAP_FAILED ((void *)-1)
|
||||
# endif
|
||||
|
||||
#endif /* HAVE_MMAP */
|
||||
#endif /* HISTORY_USE_MMAP */
|
||||
|
||||
/* If we're compiling for __EMX__ (OS/2) or __CYGWIN__ (cygwin32 environment
|
||||
on win 95/98/nt), we want to open files with O_BINARY mode so that there
|
||||
@@ -93,6 +93,13 @@ extern int errno;
|
||||
#include "rlshell.h"
|
||||
#include "xmalloc.h"
|
||||
|
||||
/* If non-zero, we write timestamps to the history file in history_do_write() */
|
||||
int history_write_timestamps = 0;
|
||||
|
||||
/* Does S look like the beginning of a history timestamp entry? Placeholder
|
||||
for more extensive tests. */
|
||||
#define HIST_TIMESTAMP_START(s) (*(s) == history_comment_char)
|
||||
|
||||
/* Return the string that should be used in the place of this
|
||||
filename. This only matters when you don't specify the
|
||||
filename to read_history (), or write_history (). */
|
||||
@@ -151,13 +158,20 @@ read_history_range (filename, from, to)
|
||||
const char *filename;
|
||||
int from, to;
|
||||
{
|
||||
register char *line_start, *line_end;
|
||||
char *input, *buffer, *bufend;
|
||||
register char *line_start, *line_end, *p;
|
||||
char *input, *buffer, *bufend, *last_ts;
|
||||
int file, current_line, chars_read;
|
||||
struct stat finfo;
|
||||
size_t file_size;
|
||||
#if defined (EFBIG)
|
||||
int overflow_errno = EFBIG;
|
||||
#elif defined (EOVERFLOW)
|
||||
int overflow_errno = EOVERFLOW;
|
||||
#else
|
||||
int overflow_errno = EIO;
|
||||
#endif
|
||||
|
||||
buffer = (char *)NULL;
|
||||
buffer = last_ts = (char *)NULL;
|
||||
input = history_filename (filename);
|
||||
file = open (input, O_RDONLY|O_BINARY, 0666);
|
||||
|
||||
@@ -169,37 +183,42 @@ read_history_range (filename, from, to)
|
||||
/* check for overflow on very large files */
|
||||
if (file_size != finfo.st_size || file_size + 1 < file_size)
|
||||
{
|
||||
#if defined (EFBIG)
|
||||
errno = EFBIG;
|
||||
#elif defined (EOVERFLOW)
|
||||
errno = EOVERFLOW;
|
||||
#endif
|
||||
errno = overflow_errno;
|
||||
goto error_and_exit;
|
||||
}
|
||||
|
||||
#ifdef HAVE_MMAP
|
||||
#ifdef HISTORY_USE_MMAP
|
||||
/* We map read/write and private so we can change newlines to NULs without
|
||||
affecting the underlying object. */
|
||||
buffer = (char *)mmap (0, file_size, PROT_READ|PROT_WRITE, MAP_RFLAGS, file, 0);
|
||||
if ((void *)buffer == MAP_FAILED)
|
||||
goto error_and_exit;
|
||||
{
|
||||
errno = overflow_errno;
|
||||
goto error_and_exit;
|
||||
}
|
||||
chars_read = file_size;
|
||||
#else
|
||||
buffer = (char *)malloc (file_size + 1);
|
||||
if (buffer == 0)
|
||||
goto error_and_exit;
|
||||
{
|
||||
errno = overflow_errno;
|
||||
goto error_and_exit;
|
||||
}
|
||||
|
||||
chars_read = read (file, buffer, file_size);
|
||||
#endif
|
||||
if (chars_read < 0)
|
||||
{
|
||||
error_and_exit:
|
||||
chars_read = errno;
|
||||
if (errno != 0)
|
||||
chars_read = errno;
|
||||
else
|
||||
chars_read = EIO;
|
||||
if (file >= 0)
|
||||
close (file);
|
||||
|
||||
FREE (input);
|
||||
#ifndef HAVE_MMAP
|
||||
#ifndef HISTORY_USE_MMAP
|
||||
FREE (buffer);
|
||||
#endif
|
||||
|
||||
@@ -220,8 +239,12 @@ read_history_range (filename, from, to)
|
||||
for (line_start = line_end = buffer; line_end < bufend && current_line < from; line_end++)
|
||||
if (*line_end == '\n')
|
||||
{
|
||||
current_line++;
|
||||
line_start = line_end + 1;
|
||||
p = line_end + 1;
|
||||
/* If we see something we think is a timestamp, continue with this
|
||||
line. We should check more extensively here... */
|
||||
if (HIST_TIMESTAMP_START(p) == 0)
|
||||
current_line++;
|
||||
line_start = p;
|
||||
}
|
||||
|
||||
/* If there are lines left to gobble, then gobble them now. */
|
||||
@@ -231,7 +254,22 @@ read_history_range (filename, from, to)
|
||||
*line_end = '\0';
|
||||
|
||||
if (*line_start)
|
||||
add_history (line_start);
|
||||
{
|
||||
if (HIST_TIMESTAMP_START(line_start) == 0)
|
||||
{
|
||||
add_history (line_start);
|
||||
if (last_ts)
|
||||
{
|
||||
add_history_time (last_ts);
|
||||
last_ts = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
last_ts = line_start;
|
||||
current_line--;
|
||||
}
|
||||
}
|
||||
|
||||
current_line++;
|
||||
|
||||
@@ -242,7 +280,7 @@ read_history_range (filename, from, to)
|
||||
}
|
||||
|
||||
FREE (input);
|
||||
#ifndef HAVE_MMAP
|
||||
#ifndef HISTORY_USE_MMAP
|
||||
FREE (buffer);
|
||||
#else
|
||||
munmap (buffer, file_size);
|
||||
@@ -259,7 +297,7 @@ history_truncate_file (fname, lines)
|
||||
const char *fname;
|
||||
int lines;
|
||||
{
|
||||
char *buffer, *filename, *bp;
|
||||
char *buffer, *filename, *bp, *bp1; /* bp1 == bp+1 */
|
||||
int file, chars_read, rv;
|
||||
struct stat finfo;
|
||||
size_t file_size;
|
||||
@@ -322,11 +360,14 @@ history_truncate_file (fname, lines)
|
||||
}
|
||||
|
||||
/* Count backwards from the end of buffer until we have passed
|
||||
LINES lines. */
|
||||
for (bp = buffer + chars_read - 1; lines && bp > buffer; bp--)
|
||||
LINES lines. bp1 is set funny initially. But since bp[1] can't
|
||||
be a comment character (since it's off the end) and *bp can't be
|
||||
both a newline and the history comment character, it should be OK. */
|
||||
for (bp1 = bp = buffer + chars_read - 1; lines && bp > buffer; bp--)
|
||||
{
|
||||
if (*bp == '\n')
|
||||
if (*bp == '\n' && HIST_TIMESTAMP_START(bp1) == 0)
|
||||
lines--;
|
||||
bp1 = bp;
|
||||
}
|
||||
|
||||
/* If this is the first line, then the file contains exactly the
|
||||
@@ -335,11 +376,14 @@ history_truncate_file (fname, lines)
|
||||
the current value of i and 0. Otherwise, write from the start of
|
||||
this line until the end of the buffer. */
|
||||
for ( ; bp > buffer; bp--)
|
||||
if (*bp == '\n')
|
||||
{
|
||||
bp++;
|
||||
break;
|
||||
}
|
||||
{
|
||||
if (*bp == '\n' && HIST_TIMESTAMP_START(bp1) == 0)
|
||||
{
|
||||
bp++;
|
||||
break;
|
||||
}
|
||||
bp1 = bp;
|
||||
}
|
||||
|
||||
/* Write only if there are more lines in the file than we want to
|
||||
truncate to. */
|
||||
@@ -374,9 +418,9 @@ history_do_write (filename, nelements, overwrite)
|
||||
register int i;
|
||||
char *output;
|
||||
int file, mode, rv;
|
||||
#ifdef HISTORY_USE_MMAP
|
||||
size_t cursize;
|
||||
|
||||
#ifdef HAVE_MMAP
|
||||
mode = overwrite ? O_RDWR|O_CREAT|O_TRUNC|O_BINARY : O_RDWR|O_APPEND|O_BINARY;
|
||||
#else
|
||||
mode = overwrite ? O_WRONLY|O_CREAT|O_TRUNC|O_BINARY : O_WRONLY|O_APPEND|O_BINARY;
|
||||
@@ -390,7 +434,7 @@ history_do_write (filename, nelements, overwrite)
|
||||
return (errno);
|
||||
}
|
||||
|
||||
#ifdef HAVE_MMAP
|
||||
#ifdef HISTORY_USE_MMAP
|
||||
cursize = overwrite ? 0 : lseek (file, 0, SEEK_END);
|
||||
#endif
|
||||
|
||||
@@ -408,10 +452,18 @@ history_do_write (filename, nelements, overwrite)
|
||||
the_history = history_list ();
|
||||
/* Calculate the total number of bytes to write. */
|
||||
for (buffer_size = 0, i = history_length - nelements; i < history_length; i++)
|
||||
buffer_size += 1 + strlen (the_history[i]->line);
|
||||
#if 0
|
||||
buffer_size += 2 + HISTENT_BYTES (the_history[i]);
|
||||
#else
|
||||
{
|
||||
if (history_write_timestamps && the_history[i]->timestamp && the_history[i]->timestamp[0])
|
||||
buffer_size += strlen (the_history[i]->timestamp) + 1;
|
||||
buffer_size += strlen (the_history[i]->line) + 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Allocate the buffer, and fill it. */
|
||||
#ifdef HAVE_MMAP
|
||||
#ifdef HISTORY_USE_MMAP
|
||||
if (ftruncate (file, buffer_size+cursize) == -1)
|
||||
goto mmap_error;
|
||||
buffer = (char *)mmap (0, buffer_size, PROT_READ|PROT_WRITE, MAP_WFLAGS, file, cursize);
|
||||
@@ -436,12 +488,18 @@ mmap_error:
|
||||
|
||||
for (j = 0, i = history_length - nelements; i < history_length; i++)
|
||||
{
|
||||
if (history_write_timestamps && the_history[i]->timestamp && the_history[i]->timestamp[0])
|
||||
{
|
||||
strcpy (buffer + j, the_history[i]->timestamp);
|
||||
j += strlen (the_history[i]->timestamp);
|
||||
buffer[j++] = '\n';
|
||||
}
|
||||
strcpy (buffer + j, the_history[i]->line);
|
||||
j += strlen (the_history[i]->line);
|
||||
buffer[j++] = '\n';
|
||||
}
|
||||
|
||||
#ifdef HAVE_MMAP
|
||||
#ifdef HISTORY_USE_MMAP
|
||||
if (msync (buffer, buffer_size, 0) != 0 || munmap (buffer, buffer_size) != 0)
|
||||
rv = errno;
|
||||
#else
|
||||
|
||||
+76
-14
@@ -1,6 +1,6 @@
|
||||
/* History.c -- standalone history library */
|
||||
/* history.c -- standalone history library */
|
||||
|
||||
/* Copyright (C) 1989, 1992 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1989-2003 Free Software Foundation, Inc.
|
||||
|
||||
This file contains the GNU History Library (the Library), a set of
|
||||
routines for managing the text of previously typed lines.
|
||||
@@ -52,6 +52,8 @@
|
||||
/* The number of slots to increase the_history by. */
|
||||
#define DEFAULT_HISTORY_GROW_SIZE 50
|
||||
|
||||
static char *hist_inittime PARAMS((void));
|
||||
|
||||
/* **************************************************************** */
|
||||
/* */
|
||||
/* History Functions */
|
||||
@@ -123,14 +125,15 @@ using_history ()
|
||||
}
|
||||
|
||||
/* Return the number of bytes that the primary history entries are using.
|
||||
This just adds up the lengths of the_history->lines. */
|
||||
This just adds up the lengths of the_history->lines and the associated
|
||||
timestamps. */
|
||||
int
|
||||
history_total_bytes ()
|
||||
{
|
||||
register int i, result;
|
||||
|
||||
for (i = result = 0; the_history && the_history[i]; i++)
|
||||
result += strlen (the_history[i]->line);
|
||||
result += HISTENT_BYTES (the_history[i]);
|
||||
|
||||
return (result);
|
||||
}
|
||||
@@ -206,6 +209,40 @@ history_get (offset)
|
||||
: the_history[local_index];
|
||||
}
|
||||
|
||||
time_t
|
||||
history_get_time (hist)
|
||||
HIST_ENTRY *hist;
|
||||
{
|
||||
char *ts;
|
||||
time_t t;
|
||||
|
||||
if (hist == 0 || hist->timestamp == 0)
|
||||
return 0;
|
||||
ts = hist->timestamp;
|
||||
if (ts[0] != history_comment_char)
|
||||
return 0;
|
||||
t = (time_t) atol (ts + 1); /* XXX - should use strtol() here */
|
||||
return t;
|
||||
}
|
||||
|
||||
static char *
|
||||
hist_inittime ()
|
||||
{
|
||||
time_t t;
|
||||
char ts[64], *ret;
|
||||
|
||||
t = (time_t) time ((time_t *)0);
|
||||
#if defined (HAVE_VSNPRINTF) /* assume snprintf if vsnprintf exists */
|
||||
snprintf (ts, sizeof (ts) - 1, "X%lu", (unsigned long) t);
|
||||
#else
|
||||
sprintf (ts, "X%lu", (unsigned long) t);
|
||||
#endif
|
||||
ret = savestring (ts);
|
||||
ret[0] = history_comment_char;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Place STRING at the end of the history list. The data field
|
||||
is set to NULL. */
|
||||
void
|
||||
@@ -225,10 +262,7 @@ add_history (string)
|
||||
|
||||
/* If there is something in the slot, then remove it. */
|
||||
if (the_history[0])
|
||||
{
|
||||
free (the_history[0]->line);
|
||||
free (the_history[0]);
|
||||
}
|
||||
(void) free_history_entry (the_history[0]);
|
||||
|
||||
/* Copy the rest of the entries, moving down one slot. */
|
||||
for (i = 0; i < history_length; i++)
|
||||
@@ -260,10 +294,41 @@ add_history (string)
|
||||
temp->line = savestring (string);
|
||||
temp->data = (char *)NULL;
|
||||
|
||||
temp->timestamp = hist_inittime ();
|
||||
|
||||
the_history[history_length] = (HIST_ENTRY *)NULL;
|
||||
the_history[history_length - 1] = temp;
|
||||
}
|
||||
|
||||
/* Change the time stamp of the most recent history entry to STRING. */
|
||||
void
|
||||
add_history_time (string)
|
||||
const char *string;
|
||||
{
|
||||
HIST_ENTRY *hs;
|
||||
|
||||
hs = the_history[history_length - 1];
|
||||
FREE (hs->timestamp);
|
||||
hs->timestamp = savestring (string);
|
||||
}
|
||||
|
||||
/* Free HIST and return the data so the calling application can free it
|
||||
if necessary and desired. */
|
||||
histdata_t
|
||||
free_history_entry (hist)
|
||||
HIST_ENTRY *hist;
|
||||
{
|
||||
histdata_t x;
|
||||
|
||||
if (hist == 0)
|
||||
return ((histdata_t) 0);
|
||||
FREE (hist->line);
|
||||
FREE (hist->timestamp);
|
||||
x = hist->data;
|
||||
free (hist);
|
||||
return (x);
|
||||
}
|
||||
|
||||
/* Make the history entry at WHICH have LINE and DATA. This returns
|
||||
the old entry so you can dispose of the data. In the case of an
|
||||
invalid WHICH, a NULL pointer is returned. */
|
||||
@@ -283,6 +348,7 @@ replace_history_entry (which, line, data)
|
||||
|
||||
temp->line = savestring (line);
|
||||
temp->data = data;
|
||||
temp->timestamp = savestring (old_value->timestamp);
|
||||
the_history[which] = temp;
|
||||
|
||||
return (old_value);
|
||||
@@ -327,10 +393,7 @@ stifle_history (max)
|
||||
{
|
||||
/* This loses because we cannot free the data. */
|
||||
for (i = 0, j = history_length - max; i < j; i++)
|
||||
{
|
||||
free (the_history[i]->line);
|
||||
free (the_history[i]);
|
||||
}
|
||||
free_history_entry (the_history[i]);
|
||||
|
||||
history_base = i;
|
||||
for (j = 0, i = history_length - max; j < max; i++, j++)
|
||||
@@ -372,8 +435,7 @@ clear_history ()
|
||||
/* This loses because we cannot free the data. */
|
||||
for (i = 0; i < history_length; i++)
|
||||
{
|
||||
free (the_history[i]->line);
|
||||
free (the_history[i]);
|
||||
free_history_entry (the_history[i]);
|
||||
the_history[i] = (HIST_ENTRY *)NULL;
|
||||
}
|
||||
|
||||
|
||||
+22
-2
@@ -1,5 +1,5 @@
|
||||
/* History.h -- the names of functions that you can call in history. */
|
||||
/* Copyright (C) 1989, 1992 Free Software Foundation, Inc.
|
||||
/* history.h -- the names of functions that you can call in history. */
|
||||
/* Copyright (C) 1989-2003 Free Software Foundation, Inc.
|
||||
|
||||
This file contains the GNU History Library (the Library), a set of
|
||||
routines for managing the text of previously typed lines.
|
||||
@@ -26,6 +26,8 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <time.h> /* XXX - for history timestamp code */
|
||||
|
||||
#if defined READLINE_LIBRARY
|
||||
# include "rlstdc.h"
|
||||
# include "rltypedefs.h"
|
||||
@@ -43,9 +45,13 @@ typedef char *histdata_t;
|
||||
/* The structure used to store a history entry. */
|
||||
typedef struct _hist_entry {
|
||||
char *line;
|
||||
char *timestamp; /* char * rather than time_t for read/write */
|
||||
histdata_t data;
|
||||
} HIST_ENTRY;
|
||||
|
||||
/* Size of the history-library-managed space in history entry HS. */
|
||||
#define HISTENT_BYTES(hs) (strlen ((hs)->line) + strlen ((hs)->timestamp))
|
||||
|
||||
/* A structure used to pass the current state of the history stuff around. */
|
||||
typedef struct _hist_state {
|
||||
HIST_ENTRY **entries; /* Pointer to the entries themselves. */
|
||||
@@ -76,11 +82,19 @@ extern void history_set_history_state PARAMS((HISTORY_STATE *));
|
||||
The associated data field (if any) is set to NULL. */
|
||||
extern void add_history PARAMS((const char *));
|
||||
|
||||
/* Change the timestamp associated with the most recent history entry to
|
||||
STRING. */
|
||||
extern void add_history_time PARAMS((const char *));
|
||||
|
||||
/* A reasonably useless function, only here for completeness. WHICH
|
||||
is the magic number that tells us which element to delete. The
|
||||
elements are numbered from 0. */
|
||||
extern HIST_ENTRY *remove_history PARAMS((int));
|
||||
|
||||
/* Free the history entry H and return any application-specific data
|
||||
associated with it. */
|
||||
extern histdata_t free_history_entry PARAMS((HIST_ENTRY *));
|
||||
|
||||
/* Make the history entry at WHICH have LINE and DATA. This returns
|
||||
the old entry so you can dispose of the data. In the case of an
|
||||
invalid WHICH, a NULL pointer is returned. */
|
||||
@@ -119,6 +133,10 @@ extern HIST_ENTRY *current_history PARAMS((void));
|
||||
array. OFFSET is relative to history_base. */
|
||||
extern HIST_ENTRY *history_get PARAMS((int));
|
||||
|
||||
/* Return the timestamp associated with the HIST_ENTRY * passed as an
|
||||
argument */
|
||||
extern time_t history_get_time PARAMS((HIST_ENTRY *));
|
||||
|
||||
/* Return the number of bytes that the primary history entries are using.
|
||||
This just adds up the lengths of the_history->lines. */
|
||||
extern int history_total_bytes PARAMS((void));
|
||||
@@ -231,6 +249,8 @@ extern char *history_no_expand_chars;
|
||||
extern char *history_search_delimiter_chars;
|
||||
extern int history_quotes_inhibit_expansion;
|
||||
|
||||
extern int history_write_timestamps;
|
||||
|
||||
/* Backwards compatibility */
|
||||
extern int max_input_history;
|
||||
|
||||
|
||||
@@ -77,11 +77,11 @@ history_search_internal (string, direction, anchored)
|
||||
if (string == 0 || *string == '\0')
|
||||
return (-1);
|
||||
|
||||
if (!history_length || ((i == history_length) && !reverse))
|
||||
if (!history_length || ((i >= history_length) && !reverse))
|
||||
return (-1);
|
||||
|
||||
if (reverse && (i == history_length))
|
||||
i--;
|
||||
if (reverse && (i >= history_length))
|
||||
i = history_length - 1;
|
||||
|
||||
#define NEXT_LINE() do { if (reverse) i--; else i++; } while (0)
|
||||
|
||||
|
||||
+13
-2
@@ -154,6 +154,12 @@ _rl_unget_char (key)
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
_rl_pushed_input_available ()
|
||||
{
|
||||
return (push_index != pop_index);
|
||||
}
|
||||
|
||||
/* If a character is available to be read, then read it and stuff it into
|
||||
IBUFFER. Otherwise, just return. Returns number of characters read
|
||||
(0 if none available) and -1 on error (EIO). */
|
||||
@@ -162,7 +168,7 @@ rl_gather_tyi ()
|
||||
{
|
||||
int tty;
|
||||
register int tem, result;
|
||||
int chars_avail;
|
||||
int chars_avail, k;
|
||||
char input;
|
||||
#if defined(HAVE_SELECT)
|
||||
fd_set readfds, exceptfds;
|
||||
@@ -225,7 +231,12 @@ rl_gather_tyi ()
|
||||
if (result != -1)
|
||||
{
|
||||
while (chars_avail--)
|
||||
rl_stuff_char ((*rl_getc_function) (rl_instream));
|
||||
{
|
||||
k = (*rl_getc_function) (rl_instream);
|
||||
rl_stuff_char (k);
|
||||
if (k == NEWLINE || k == RETURN)
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -64,11 +64,13 @@ rl_make_bare_keymap ()
|
||||
keymap[i].function = (rl_command_func_t *)NULL;
|
||||
}
|
||||
|
||||
#if 0
|
||||
for (i = 'A'; i < ('Z' + 1); i++)
|
||||
{
|
||||
keymap[i].type = ISFUNC;
|
||||
keymap[i].function = rl_do_lowercase_version;
|
||||
}
|
||||
#endif
|
||||
|
||||
return (keymap);
|
||||
}
|
||||
@@ -79,8 +81,9 @@ rl_copy_keymap (map)
|
||||
Keymap map;
|
||||
{
|
||||
register int i;
|
||||
Keymap temp = rl_make_bare_keymap ();
|
||||
Keymap temp;
|
||||
|
||||
temp = rl_make_bare_keymap ();
|
||||
for (i = 0; i < KEYMAP_SIZE; i++)
|
||||
{
|
||||
temp[i].type = map[i].type;
|
||||
@@ -109,12 +112,8 @@ rl_make_keymap ()
|
||||
newmap[CTRL('H')].function = rl_rubout;
|
||||
|
||||
#if KEYMAP_SIZE > 128
|
||||
/* Printing characters in some 8-bit character sets. */
|
||||
for (i = 128; i < 160; i++)
|
||||
newmap[i].function = rl_insert;
|
||||
|
||||
/* ISO Latin-1 printing characters should self-insert. */
|
||||
for (i = 160; i < 256; i++)
|
||||
/* Printing characters in ISO Latin-1 and some 8-bit character sets. */
|
||||
for (i = 128; i < 256; i++)
|
||||
newmap[i].function = rl_insert;
|
||||
#endif /* KEYMAP_SIZE > 128 */
|
||||
|
||||
|
||||
+20
-13
@@ -97,7 +97,7 @@ _rl_find_next_mbchar_internal (string, seed, count, find_non_zero)
|
||||
while (count > 0)
|
||||
{
|
||||
tmp = mbrtowc (&wc, string+point, strlen(string + point), &ps);
|
||||
if ((size_t)(tmp) == (size_t)-1 || (size_t)(tmp) == (size_t)-2)
|
||||
if (MB_INVALIDCH ((size_t)tmp))
|
||||
{
|
||||
/* invalid bytes. asume a byte represents a character */
|
||||
point++;
|
||||
@@ -105,9 +105,8 @@ _rl_find_next_mbchar_internal (string, seed, count, find_non_zero)
|
||||
/* reset states. */
|
||||
memset(&ps, 0, sizeof(mbstate_t));
|
||||
}
|
||||
else if (tmp == (size_t)0)
|
||||
/* found '\0' char */
|
||||
break;
|
||||
else if (MB_NULLWCH (tmp))
|
||||
break; /* found wide '\0' */
|
||||
else
|
||||
{
|
||||
/* valid bytes */
|
||||
@@ -160,7 +159,7 @@ _rl_find_prev_mbchar_internal (string, seed, find_non_zero)
|
||||
while (point < seed)
|
||||
{
|
||||
tmp = mbrtowc (&wc, string + point, length - point, &ps);
|
||||
if ((size_t)(tmp) == (size_t)-1 || (size_t)(tmp) == (size_t)-2)
|
||||
if (MB_INVALIDCH ((size_t)tmp))
|
||||
{
|
||||
/* in this case, bytes are invalid or shorted to compose
|
||||
multibyte char, so assume that the first byte represents
|
||||
@@ -170,7 +169,7 @@ _rl_find_prev_mbchar_internal (string, seed, find_non_zero)
|
||||
in this case effect of mbstate is undefined */
|
||||
memset(&ps, 0, sizeof (mbstate_t));
|
||||
}
|
||||
else if (tmp == 0)
|
||||
else if (MB_NULLWCH (tmp))
|
||||
break; /* Found '\0' char. Can this happen? */
|
||||
else
|
||||
{
|
||||
@@ -205,14 +204,16 @@ _rl_get_char_len (src, ps)
|
||||
if (tmp == (size_t)(-2))
|
||||
{
|
||||
/* shorted to compose multibyte char */
|
||||
memset (ps, 0, sizeof(mbstate_t));
|
||||
if (ps)
|
||||
memset (ps, 0, sizeof(mbstate_t));
|
||||
return -2;
|
||||
}
|
||||
else if (tmp == (size_t)(-1))
|
||||
{
|
||||
/* invalid to compose multibyte char */
|
||||
/* initialize the conversion state */
|
||||
memset (ps, 0, sizeof(mbstate_t));
|
||||
if (ps)
|
||||
memset (ps, 0, sizeof(mbstate_t));
|
||||
return -1;
|
||||
}
|
||||
else if (tmp == (size_t)0)
|
||||
@@ -225,9 +226,12 @@ _rl_get_char_len (src, ps)
|
||||
return 1. Otherwise return 0. */
|
||||
int
|
||||
_rl_compare_chars (buf1, pos1, ps1, buf2, pos2, ps2)
|
||||
char *buf1, *buf2;
|
||||
mbstate_t *ps1, *ps2;
|
||||
int pos1, pos2;
|
||||
char *buf1;
|
||||
int pos1;
|
||||
mbstate_t *ps1;
|
||||
char *buf2;
|
||||
int pos2;
|
||||
mbstate_t *ps2;
|
||||
{
|
||||
int i, w1, w2;
|
||||
|
||||
@@ -268,7 +272,7 @@ _rl_adjust_point(string, point, ps)
|
||||
while (pos < point)
|
||||
{
|
||||
tmp = mbrlen (string + pos, length - pos, ps);
|
||||
if((size_t)(tmp) == (size_t)-1 || (size_t)(tmp) == (size_t)-2)
|
||||
if (MB_INVALIDCH ((size_t)tmp))
|
||||
{
|
||||
/* in this case, bytes are invalid or shorted to compose
|
||||
multibyte char, so assume that the first byte represents
|
||||
@@ -276,8 +280,11 @@ _rl_adjust_point(string, point, ps)
|
||||
pos++;
|
||||
/* clear the state of the byte sequence, because
|
||||
in this case effect of mbstate is undefined */
|
||||
memset (ps, 0, sizeof (mbstate_t));
|
||||
if (ps)
|
||||
memset (ps, 0, sizeof (mbstate_t));
|
||||
}
|
||||
else if (MB_NULLWCH (tmp))
|
||||
pos++;
|
||||
else
|
||||
pos += tmp;
|
||||
}
|
||||
|
||||
+4
-2
@@ -253,7 +253,7 @@ rl_maybe_unsave_line ()
|
||||
{
|
||||
if (_rl_saved_line_for_history)
|
||||
{
|
||||
rl_replace_line (_rl_saved_line_for_history->line, 0);
|
||||
rl_replace_line (_rl_saved_line_for_history->line, 1);
|
||||
rl_undo_list = (UNDO_LIST *)_rl_saved_line_for_history->data;
|
||||
_rl_free_history_entry (_rl_saved_line_for_history);
|
||||
_rl_saved_line_for_history = (HIST_ENTRY *)NULL;
|
||||
@@ -298,7 +298,7 @@ _rl_history_set_point ()
|
||||
rl_point = rl_end;
|
||||
|
||||
#if defined (VI_MODE)
|
||||
if (rl_editing_mode == vi_mode)
|
||||
if (rl_editing_mode == vi_mode && _rl_keymap != vi_insertion_keymap)
|
||||
rl_point = 0;
|
||||
#endif /* VI_MODE */
|
||||
|
||||
@@ -311,6 +311,8 @@ rl_replace_from_history (entry, flags)
|
||||
HIST_ENTRY *entry;
|
||||
int flags; /* currently unused */
|
||||
{
|
||||
/* Can't call with `1' because rl_undo_list might point to an undo list
|
||||
from a history entry, just like we're setting up here. */
|
||||
rl_replace_line (entry->line, 0);
|
||||
rl_undo_list = (UNDO_LIST *)entry->data;
|
||||
rl_point = rl_end;
|
||||
|
||||
+32
-5
@@ -75,6 +75,23 @@ static char *normalize_codeset PARAMS((char *));
|
||||
static char *find_codeset PARAMS((char *, size_t *));
|
||||
#endif /* !HAVE_SETLOCALE */
|
||||
|
||||
static char *_rl_get_locale_var PARAMS((const char *));
|
||||
|
||||
static char *
|
||||
_rl_get_locale_var (v)
|
||||
const char *v;
|
||||
{
|
||||
char *lspec;
|
||||
|
||||
lspec = sh_get_env_value ("LC_ALL");
|
||||
if (lspec == 0 || *lspec == 0)
|
||||
lspec = sh_get_env_value (v);
|
||||
if (lspec == 0 || *lspec == 0)
|
||||
lspec = sh_get_env_value ("LANG");
|
||||
|
||||
return lspec;
|
||||
}
|
||||
|
||||
/* Check for LC_ALL, LC_CTYPE, and LANG and use the first with a value
|
||||
to decide the defaults for 8-bit character input and output. Returns
|
||||
1 if we set eight-bit mode. */
|
||||
@@ -84,10 +101,21 @@ _rl_init_eightbit ()
|
||||
/* If we have setlocale(3), just check the current LC_CTYPE category
|
||||
value, and go into eight-bit mode if it's not C or POSIX. */
|
||||
#if defined (HAVE_SETLOCALE)
|
||||
char *t;
|
||||
char *lspec, *t;
|
||||
|
||||
/* Set the LC_CTYPE locale category from environment variables. */
|
||||
t = setlocale (LC_CTYPE, "");
|
||||
lspec = _rl_get_locale_var ("LC_CTYPE");
|
||||
/* Since _rl_get_locale_var queries the right environment variables,
|
||||
we query the current locale settings with setlocale(), and, if
|
||||
that doesn't return anything, we set lspec to the empty string to
|
||||
force the subsequent call to setlocale() to define the `native'
|
||||
environment. */
|
||||
if (lspec == 0 || *lspec == 0)
|
||||
lspec = setlocale (LC_CTYPE, (char *)NULL);
|
||||
if (lspec == 0)
|
||||
lspec = "";
|
||||
t = setlocale (LC_CTYPE, lspec);
|
||||
|
||||
if (t && *t && (t[0] != 'C' || t[1]) && (STREQ (t, "POSIX") == 0))
|
||||
{
|
||||
_rl_meta_flag = 1;
|
||||
@@ -105,9 +133,8 @@ _rl_init_eightbit ()
|
||||
/* We don't have setlocale. Finesse it. Check the environment for the
|
||||
appropriate variables and set eight-bit mode if they have the right
|
||||
values. */
|
||||
lspec = sh_get_env_value ("LC_ALL");
|
||||
if (lspec == 0) lspec = sh_get_env_value ("LC_CTYPE");
|
||||
if (lspec == 0) lspec = sh_get_env_value ("LANG");
|
||||
lspec = _rl_get_locale_var ("LC_CTYPE");
|
||||
|
||||
if (lspec == 0 || (t = normalize_codeset (lspec)) == 0)
|
||||
return (0);
|
||||
for (i = 0; t && legal_lang_values[i]; i++)
|
||||
|
||||
+46
-21
@@ -68,11 +68,11 @@
|
||||
#include "xmalloc.h"
|
||||
|
||||
#ifndef RL_LIBRARY_VERSION
|
||||
# define RL_LIBRARY_VERSION "4.3"
|
||||
# define RL_LIBRARY_VERSION "5.0"
|
||||
#endif
|
||||
|
||||
#ifndef RL_READLINE_VERSION
|
||||
# define RL_READLINE_VERSION 0x0403
|
||||
# define RL_READLINE_VERSION 0x0500
|
||||
#endif
|
||||
|
||||
extern void _rl_free_history_entry PARAMS((HIST_ENTRY *));
|
||||
@@ -85,6 +85,7 @@ static void bind_arrow_keys_internal PARAMS((Keymap));
|
||||
static void bind_arrow_keys PARAMS((void));
|
||||
|
||||
static void readline_default_bindings PARAMS((void));
|
||||
static void reset_default_bindings PARAMS((void));
|
||||
|
||||
/* **************************************************************** */
|
||||
/* */
|
||||
@@ -347,7 +348,7 @@ readline_internal_setup ()
|
||||
|
||||
#if defined (VI_MODE)
|
||||
if (rl_editing_mode == vi_mode)
|
||||
rl_vi_insertion_mode (1, 0);
|
||||
rl_vi_insertion_mode (1, 'i');
|
||||
#endif /* VI_MODE */
|
||||
|
||||
if (rl_pre_input_hook)
|
||||
@@ -650,7 +651,21 @@ _rl_dispatch_subseq (key, map, got_subseq)
|
||||
the function. The recursive call to _rl_dispatch_subseq has
|
||||
already taken care of pushing any necessary input back onto
|
||||
the input queue with _rl_unget_char. */
|
||||
r = _rl_dispatch (ANYOTHERKEY, FUNCTION_TO_KEYMAP (map, key));
|
||||
{
|
||||
#if 0
|
||||
r = _rl_dispatch (ANYOTHERKEY, FUNCTION_TO_KEYMAP (map, key));
|
||||
#else
|
||||
/* XXX - experimental code -- might never be executed. Save
|
||||
for later. */
|
||||
Keymap m = FUNCTION_TO_KEYMAP (map, key);
|
||||
int type = m[ANYOTHERKEY].type;
|
||||
func = m[ANYOTHERKEY].function;
|
||||
if (type == ISFUNC && func == rl_do_lowercase_version)
|
||||
r = _rl_dispatch (_rl_to_lower (key), map);
|
||||
else
|
||||
r = _rl_dispatch (ANYOTHERKEY, m);
|
||||
#endif
|
||||
}
|
||||
else if (r && map[ANYOTHERKEY].function)
|
||||
{
|
||||
/* We didn't match (r is probably -1), so return something to
|
||||
@@ -684,6 +699,7 @@ _rl_dispatch_subseq (key, map, got_subseq)
|
||||
}
|
||||
#if defined (VI_MODE)
|
||||
if (rl_editing_mode == vi_mode && _rl_keymap == vi_movement_keymap &&
|
||||
key != ANYOTHERKEY &&
|
||||
_rl_vi_textmod_command (key))
|
||||
_rl_vi_set_last (key, rl_numeric_arg, rl_arg_sign);
|
||||
#endif
|
||||
@@ -838,7 +854,7 @@ readline_initialize_everything ()
|
||||
/* If the completion parser's default word break characters haven't
|
||||
been set yet, then do so now. */
|
||||
if (rl_completer_word_break_characters == (char *)NULL)
|
||||
rl_completer_word_break_characters = rl_basic_word_break_characters;
|
||||
rl_completer_word_break_characters = (char *)rl_basic_word_break_characters;
|
||||
}
|
||||
|
||||
/* If this system allows us to look at the values of the regular
|
||||
@@ -850,6 +866,15 @@ readline_default_bindings ()
|
||||
rl_tty_set_default_bindings (_rl_keymap);
|
||||
}
|
||||
|
||||
/* Reset the default bindings for the terminal special characters we're
|
||||
interested in back to rl_insert and read the new ones. */
|
||||
static void
|
||||
reset_default_bindings ()
|
||||
{
|
||||
rl_tty_unset_default_bindings (_rl_keymap);
|
||||
rl_tty_set_default_bindings (_rl_keymap);
|
||||
}
|
||||
|
||||
/* Bind some common arrow key sequences in MAP. */
|
||||
static void
|
||||
bind_arrow_keys_internal (map)
|
||||
@@ -861,25 +886,25 @@ bind_arrow_keys_internal (map)
|
||||
_rl_keymap = map;
|
||||
|
||||
#if defined (__MSDOS__)
|
||||
_rl_bind_if_unbound ("\033[0A", rl_get_previous_history);
|
||||
_rl_bind_if_unbound ("\033[0B", rl_backward_char);
|
||||
_rl_bind_if_unbound ("\033[0C", rl_forward_char);
|
||||
_rl_bind_if_unbound ("\033[0D", rl_get_next_history);
|
||||
rl_bind_keyseq_if_unbound ("\033[0A", rl_get_previous_history);
|
||||
rl_bind_keyseq_if_unbound ("\033[0B", rl_backward_char);
|
||||
rl_bind_keyseq_if_unbound ("\033[0C", rl_forward_char);
|
||||
rl_bind_keyseq_if_unbound ("\033[0D", rl_get_next_history);
|
||||
#endif
|
||||
|
||||
_rl_bind_if_unbound ("\033[A", rl_get_previous_history);
|
||||
_rl_bind_if_unbound ("\033[B", rl_get_next_history);
|
||||
_rl_bind_if_unbound ("\033[C", rl_forward_char);
|
||||
_rl_bind_if_unbound ("\033[D", rl_backward_char);
|
||||
_rl_bind_if_unbound ("\033[H", rl_beg_of_line);
|
||||
_rl_bind_if_unbound ("\033[F", rl_end_of_line);
|
||||
rl_bind_keyseq_if_unbound ("\033[A", rl_get_previous_history);
|
||||
rl_bind_keyseq_if_unbound ("\033[B", rl_get_next_history);
|
||||
rl_bind_keyseq_if_unbound ("\033[C", rl_forward_char);
|
||||
rl_bind_keyseq_if_unbound ("\033[D", rl_backward_char);
|
||||
rl_bind_keyseq_if_unbound ("\033[H", rl_beg_of_line);
|
||||
rl_bind_keyseq_if_unbound ("\033[F", rl_end_of_line);
|
||||
|
||||
_rl_bind_if_unbound ("\033OA", rl_get_previous_history);
|
||||
_rl_bind_if_unbound ("\033OB", rl_get_next_history);
|
||||
_rl_bind_if_unbound ("\033OC", rl_forward_char);
|
||||
_rl_bind_if_unbound ("\033OD", rl_backward_char);
|
||||
_rl_bind_if_unbound ("\033OH", rl_beg_of_line);
|
||||
_rl_bind_if_unbound ("\033OF", rl_end_of_line);
|
||||
rl_bind_keyseq_if_unbound ("\033OA", rl_get_previous_history);
|
||||
rl_bind_keyseq_if_unbound ("\033OB", rl_get_next_history);
|
||||
rl_bind_keyseq_if_unbound ("\033OC", rl_forward_char);
|
||||
rl_bind_keyseq_if_unbound ("\033OD", rl_backward_char);
|
||||
rl_bind_keyseq_if_unbound ("\033OH", rl_beg_of_line);
|
||||
rl_bind_keyseq_if_unbound ("\033OF", rl_end_of_line);
|
||||
|
||||
_rl_keymap = xkeymap;
|
||||
}
|
||||
|
||||
+16
-6
@@ -40,9 +40,9 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
/* Hex-encoded Readline version number. */
|
||||
#define RL_READLINE_VERSION 0x0403 /* Readline 4.3 */
|
||||
#define RL_VERSION_MAJOR 4
|
||||
#define RL_VERSION_MINOR 3
|
||||
#define RL_READLINE_VERSION 0x0500 /* Readline 5.0 */
|
||||
#define RL_VERSION_MAJOR 5
|
||||
#define RL_VERSION_MINOR 0
|
||||
|
||||
/* Readline data structures. */
|
||||
|
||||
@@ -290,12 +290,20 @@ extern int rl_bind_key PARAMS((int, rl_command_func_t *));
|
||||
extern int rl_bind_key_in_map PARAMS((int, rl_command_func_t *, Keymap));
|
||||
extern int rl_unbind_key PARAMS((int));
|
||||
extern int rl_unbind_key_in_map PARAMS((int, Keymap));
|
||||
extern int rl_bind_key_if_unbound PARAMS((int, rl_command_func_t *));
|
||||
extern int rl_bind_key_if_unbound_in_map PARAMS((int, rl_command_func_t *, Keymap));
|
||||
extern int rl_unbind_function_in_map PARAMS((rl_command_func_t *, Keymap));
|
||||
extern int rl_unbind_command_in_map PARAMS((const char *, Keymap));
|
||||
extern int rl_set_key PARAMS((const char *, rl_command_func_t *, Keymap));
|
||||
extern int rl_bind_keyseq PARAMS((const char *, rl_command_func_t *));
|
||||
extern int rl_bind_keyseq_in_map PARAMS((const char *, rl_command_func_t *, Keymap));
|
||||
extern int rl_bind_keyseq_if_unbound PARAMS((const char *, rl_command_func_t *));
|
||||
extern int rl_bind_keyseq_if_unbound_in_map PARAMS((const char *, rl_command_func_t *, Keymap));
|
||||
extern int rl_generic_bind PARAMS((int, const char *, char *, Keymap));
|
||||
extern int rl_variable_bind PARAMS((const char *, const char *));
|
||||
|
||||
/* Backwards compatibility, use rl_bind_keyseq_in_map instead. */
|
||||
extern int rl_set_key PARAMS((const char *, rl_command_func_t *, Keymap));
|
||||
|
||||
/* Backwards compatibility, use rl_generic_bind instead. */
|
||||
extern int rl_macro_bind PARAMS((const char *, const char *, Keymap));
|
||||
|
||||
@@ -358,7 +366,7 @@ extern int rl_clear_message PARAMS((void));
|
||||
extern int rl_reset_line_state PARAMS((void));
|
||||
extern int rl_crlf PARAMS((void));
|
||||
|
||||
#if (defined (__STDC__) || defined (__cplusplus)) && defined (USE_VARARGS) && defined (PREFER_STDARG)
|
||||
#if defined (USE_VARARGS) && defined (PREFER_STDARG)
|
||||
extern int rl_message (const char *, ...) __attribute__((__format__ (printf, 1, 2)));
|
||||
#else
|
||||
extern int rl_message ();
|
||||
@@ -384,6 +392,7 @@ extern char *rl_copy_text PARAMS((int, int));
|
||||
extern void rl_prep_terminal PARAMS((int));
|
||||
extern void rl_deprep_terminal PARAMS((void));
|
||||
extern void rl_tty_set_default_bindings PARAMS((Keymap));
|
||||
extern void rl_tty_unset_default_bindings PARAMS((Keymap));
|
||||
|
||||
extern int rl_reset_terminal PARAMS((const char *));
|
||||
extern void rl_resize_terminal PARAMS((void));
|
||||
@@ -603,7 +612,7 @@ extern const char *rl_basic_word_break_characters;
|
||||
/* The list of characters that signal a break between words for
|
||||
rl_complete_internal. The default list is the contents of
|
||||
rl_basic_word_break_characters. */
|
||||
extern const char *rl_completer_word_break_characters;
|
||||
extern /*const*/ char *rl_completer_word_break_characters;
|
||||
|
||||
/* List of characters which can be used to quote a substring of the line.
|
||||
Completion occurs on the entire substring, and within the substring
|
||||
@@ -749,6 +758,7 @@ extern int rl_inhibit_completion;
|
||||
#define RL_STATE_SIGHANDLER 0x08000 /* in readline sighandler */
|
||||
#define RL_STATE_UNDOING 0x10000 /* doing an undo */
|
||||
#define RL_STATE_INPUTPENDING 0x20000 /* rl_execute_next called */
|
||||
#define RL_STATE_TTYCSAVED 0x40000 /* tty special chars saved */
|
||||
|
||||
#define RL_STATE_DONE 0x80000 /* done; accepted line */
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ extern int _rl_stricmp PARAMS((char *, char *));
|
||||
extern int _rl_strnicmp PARAMS((char *, char *, int));
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_STRPBRK)
|
||||
#if defined (HAVE_STRPBRK) && !defined (HAVE_MULTIBYTE)
|
||||
# define _rl_strpbrk(a,b) strpbrk((a),(b))
|
||||
#else
|
||||
extern char *_rl_strpbrk PARAMS((const char *, const char *));
|
||||
|
||||
+14
-1
@@ -35,11 +35,18 @@
|
||||
#if defined (HAVE_WCTYPE_H) && defined (HAVE_WCHAR_H)
|
||||
# include <wchar.h>
|
||||
# include <wctype.h>
|
||||
# if defined (HAVE_MBSRTOWCS) /* system is supposed to support XPG5 */
|
||||
# if defined (HAVE_MBSRTOWCS) && defined (HAVE_MBRTOWC) && defined (HAVE_MBRLEN) && defined (HAVE_WCWIDTH)
|
||||
/* system is supposed to support XPG5 */
|
||||
# define HANDLE_MULTIBYTE 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* If we don't want multibyte chars even on a system that supports them, let
|
||||
the configuring user turn multibyte support off. */
|
||||
#if defined (NO_MULTIBYTE_SUPPORT)
|
||||
# undef HANDLE_MULTIBYTE
|
||||
#endif
|
||||
|
||||
/* Some systems, like BeOS, have multibyte encodings but lack mbstate_t. */
|
||||
#if HANDLE_MULTIBYTE && !defined (HAVE_MBSTATE_T)
|
||||
# define wcsrtombs(dest, src, len, ps) (wcsrtombs) (dest, src, len, 0)
|
||||
@@ -90,6 +97,9 @@ extern int _rl_read_mbstring PARAMS((int, char *, int));
|
||||
|
||||
extern int _rl_is_mbchar_matched PARAMS((char *, int, int, char *, int));
|
||||
|
||||
#define MB_INVALIDCH(x) ((x) == (size_t)-1 || (x) == (size_t)-2)
|
||||
#define MB_NULLWCH(x) ((x) == 0)
|
||||
|
||||
#else /* !HANDLE_MULTIBYTE */
|
||||
|
||||
#undef MB_LEN_MAX
|
||||
@@ -101,6 +111,9 @@ extern int _rl_is_mbchar_matched PARAMS((char *, int, int, char *, int));
|
||||
#define _rl_find_prev_mbchar(b, i, f) (((i) == 0) ? (i) : ((i) - 1))
|
||||
#define _rl_find_next_mbchar(b, i1, i2, f) ((i1) + (i2))
|
||||
|
||||
#define MB_INVALIDCH(x) (0)
|
||||
#define MB_NULLWCH(x) (0)
|
||||
|
||||
#endif /* !HANDLE_MULTIBYTE */
|
||||
|
||||
extern int rl_byte_oriented;
|
||||
|
||||
@@ -103,7 +103,6 @@ extern int readline_internal_char PARAMS((void));
|
||||
#endif /* READLINE_CALLBACKS */
|
||||
|
||||
/* bind.c */
|
||||
extern void _rl_bind_if_unbound PARAMS((const char *, rl_command_func_t *));
|
||||
|
||||
/* complete.c */
|
||||
extern char _rl_find_completion_word PARAMS((int *, int *));
|
||||
@@ -131,6 +130,7 @@ extern int _rl_input_available PARAMS((void));
|
||||
extern int _rl_input_queued PARAMS((int));
|
||||
extern void _rl_insert_typein PARAMS((int));
|
||||
extern int _rl_unget_char PARAMS((int));
|
||||
extern int _rl_pushed_input_available PARAMS((void));
|
||||
|
||||
/* macro.c */
|
||||
extern void _rl_with_macro_input PARAMS((char *));
|
||||
@@ -219,6 +219,7 @@ extern const char *_rl_possible_meta_prefixes[];
|
||||
|
||||
/* complete.c */
|
||||
extern int _rl_complete_show_all;
|
||||
extern int _rl_complete_show_unmodified;
|
||||
extern int _rl_complete_mark_directories;
|
||||
extern int _rl_complete_mark_symlink_dirs;
|
||||
extern int _rl_print_completions_horizontally;
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
#endif
|
||||
|
||||
#ifndef __attribute__
|
||||
# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8) || __STRICT_ANSI__
|
||||
# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8)
|
||||
# define __attribute__(x)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
+113
-54
@@ -186,6 +186,8 @@ static int set_tty_settings PARAMS((int, TIOTYPE *));
|
||||
|
||||
static void prepare_terminal_settings PARAMS((int, TIOTYPE, TIOTYPE *));
|
||||
|
||||
static void set_special_char PARAMS((Keymap, TIOTYPE *, int, rl_command_func_t));
|
||||
|
||||
static void
|
||||
save_tty_chars (tiop)
|
||||
TIOTYPE *tiop;
|
||||
@@ -400,6 +402,9 @@ static int set_tty_settings PARAMS((int, TIOTYPE *));
|
||||
|
||||
static void prepare_terminal_settings PARAMS((int, TIOTYPE, TIOTYPE *));
|
||||
|
||||
static void set_special_char PARAMS((Keymap, TIOTYPE *, int, rl_command_func_t));
|
||||
static void _rl_bind_tty_special_chars PARAMS((Keymap, TIOTYPE));
|
||||
|
||||
#if defined (FLUSHO)
|
||||
# define OUTPUT_BEING_FLUSHED(tp) (tp->c_lflag & FLUSHO)
|
||||
#else
|
||||
@@ -652,7 +657,10 @@ rl_prep_terminal (meta_flag)
|
||||
|
||||
otio = tio;
|
||||
|
||||
rl_tty_unset_default_bindings (_rl_keymap);
|
||||
save_tty_chars (&otio);
|
||||
RL_SETSTATE(RL_STATE_TTYCSAVED);
|
||||
_rl_bind_tty_special_chars (_rl_keymap, tio);
|
||||
|
||||
prepare_terminal_settings (meta_flag, otio, &tio);
|
||||
|
||||
@@ -776,6 +784,83 @@ rl_stop_output (count, key)
|
||||
/* */
|
||||
/* **************************************************************** */
|
||||
|
||||
#define SET_SPECIAL(sc, func) set_special_char(kmap, &ttybuff, sc, func)
|
||||
|
||||
#if defined (NEW_TTY_DRIVER)
|
||||
static void
|
||||
set_special_char (kmap, tiop, sc, func)
|
||||
Keymap kmap;
|
||||
TIOTYPE *tiop;
|
||||
int sc;
|
||||
rl_command_func_t *func;
|
||||
{
|
||||
if (sc != -1 && kmap[(unsigned char)sc].type == ISFUNC)
|
||||
kmap[(unsigned char)sc].function = func;
|
||||
}
|
||||
|
||||
#define RESET_SPECIAL(c) \
|
||||
if (c != -1 && kmap[(unsigned char)c].type == ISFUNC)
|
||||
kmap[(unsigned char)c].function = rl_insert;
|
||||
|
||||
static void
|
||||
_rl_bind_tty_special_chars (kmap, ttybuff)
|
||||
Keymap kmap;
|
||||
TIOTYPE ttybuff;
|
||||
{
|
||||
if (ttybuff.flags & SGTTY_SET)
|
||||
{
|
||||
SET_SPECIAL (ttybuff.sgttyb.sg_erase, rl_rubout);
|
||||
SET_SPECIAL (ttybuff.sgttyb.sg_kill, rl_unix_line_discard);
|
||||
}
|
||||
|
||||
# if defined (TIOCGLTC)
|
||||
if (ttybuff.flags & LTCHARS_SET)
|
||||
{
|
||||
SET_SPECIAL (ttybuff.ltchars.t_werasc, rl_unix_word_rubout);
|
||||
SET_SPECIAL (ttybuff.ltchars.t_lnextc, rl_quoted_insert);
|
||||
}
|
||||
# endif /* TIOCGLTC */
|
||||
}
|
||||
|
||||
#else /* !NEW_TTY_DRIVER */
|
||||
static void
|
||||
set_special_char (kmap, tiop, sc, func)
|
||||
Keymap kmap;
|
||||
TIOTYPE *tiop;
|
||||
int sc;
|
||||
rl_command_func_t *func;
|
||||
{
|
||||
unsigned char uc;
|
||||
|
||||
uc = tiop->c_cc[sc];
|
||||
if (uc != (unsigned char)_POSIX_VDISABLE && kmap[uc].type == ISFUNC)
|
||||
kmap[uc].function = func;
|
||||
}
|
||||
|
||||
/* used later */
|
||||
#define RESET_SPECIAL(uc) \
|
||||
if (uc != (unsigned char)_POSIX_VDISABLE && kmap[uc].type == ISFUNC) \
|
||||
kmap[uc].function = rl_insert;
|
||||
|
||||
static void
|
||||
_rl_bind_tty_special_chars (kmap, ttybuff)
|
||||
Keymap kmap;
|
||||
TIOTYPE ttybuff;
|
||||
{
|
||||
SET_SPECIAL (VERASE, rl_rubout);
|
||||
SET_SPECIAL (VKILL, rl_unix_line_discard);
|
||||
|
||||
# if defined (VLNEXT) && defined (TERMIOS_TTY_DRIVER)
|
||||
SET_SPECIAL (VLNEXT, rl_quoted_insert);
|
||||
# endif /* VLNEXT && TERMIOS_TTY_DRIVER */
|
||||
|
||||
# if defined (VWERASE) && defined (TERMIOS_TTY_DRIVER)
|
||||
SET_SPECIAL (VWERASE, rl_unix_word_rubout);
|
||||
# endif /* VWERASE && TERMIOS_TTY_DRIVER */
|
||||
}
|
||||
|
||||
#endif /* !NEW_TTY_DRIVER */
|
||||
|
||||
/* Set the system's default editing characters to their readline equivalents
|
||||
in KMAP. Should be static, now that we have rl_tty_set_default_bindings. */
|
||||
void
|
||||
@@ -783,63 +868,13 @@ rltty_set_default_bindings (kmap)
|
||||
Keymap kmap;
|
||||
{
|
||||
TIOTYPE ttybuff;
|
||||
int tty = fileno (rl_instream);
|
||||
int tty;
|
||||
static int called = 0;
|
||||
|
||||
#if defined (NEW_TTY_DRIVER)
|
||||
|
||||
#define SET_SPECIAL(sc, func) \
|
||||
do \
|
||||
{ \
|
||||
int ic; \
|
||||
ic = sc; \
|
||||
if (ic != -1 && kmap[(unsigned char)ic].type == ISFUNC) \
|
||||
kmap[(unsigned char)ic].function = func; \
|
||||
} \
|
||||
while (0)
|
||||
tty = fileno (rl_instream);
|
||||
|
||||
if (get_tty_settings (tty, &ttybuff) == 0)
|
||||
{
|
||||
if (ttybuff.flags & SGTTY_SET)
|
||||
{
|
||||
SET_SPECIAL (ttybuff.sgttyb.sg_erase, rl_rubout);
|
||||
SET_SPECIAL (ttybuff.sgttyb.sg_kill, rl_unix_line_discard);
|
||||
}
|
||||
|
||||
# if defined (TIOCGLTC)
|
||||
if (ttybuff.flags & LTCHARS_SET)
|
||||
{
|
||||
SET_SPECIAL (ttybuff.ltchars.t_werasc, rl_unix_word_rubout);
|
||||
SET_SPECIAL (ttybuff.ltchars.t_lnextc, rl_quoted_insert);
|
||||
}
|
||||
# endif /* TIOCGLTC */
|
||||
}
|
||||
|
||||
#else /* !NEW_TTY_DRIVER */
|
||||
|
||||
#define SET_SPECIAL(sc, func) \
|
||||
do \
|
||||
{ \
|
||||
unsigned char uc; \
|
||||
uc = ttybuff.c_cc[sc]; \
|
||||
if (uc != (unsigned char)_POSIX_VDISABLE && kmap[uc].type == ISFUNC) \
|
||||
kmap[uc].function = func; \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
if (get_tty_settings (tty, &ttybuff) == 0)
|
||||
{
|
||||
SET_SPECIAL (VERASE, rl_rubout);
|
||||
SET_SPECIAL (VKILL, rl_unix_line_discard);
|
||||
|
||||
# if defined (VLNEXT) && defined (TERMIOS_TTY_DRIVER)
|
||||
SET_SPECIAL (VLNEXT, rl_quoted_insert);
|
||||
# endif /* VLNEXT && TERMIOS_TTY_DRIVER */
|
||||
|
||||
# if defined (VWERASE) && defined (TERMIOS_TTY_DRIVER)
|
||||
SET_SPECIAL (VWERASE, rl_unix_word_rubout);
|
||||
# endif /* VWERASE && TERMIOS_TTY_DRIVER */
|
||||
}
|
||||
#endif /* !NEW_TTY_DRIVER */
|
||||
_rl_bind_tty_special_chars (kmap, ttybuff);
|
||||
}
|
||||
|
||||
/* New public way to set the system default editing chars to their readline
|
||||
@@ -851,6 +886,30 @@ rl_tty_set_default_bindings (kmap)
|
||||
rltty_set_default_bindings (kmap);
|
||||
}
|
||||
|
||||
/* Rebind all of the tty special chars that readline worries about back
|
||||
to self-insert. Call this before saving the current terminal special
|
||||
chars with save_tty_chars(). This only works on POSIX termios or termio
|
||||
systems. */
|
||||
void
|
||||
rl_tty_unset_default_bindings (kmap)
|
||||
Keymap kmap;
|
||||
{
|
||||
/* Don't bother before we've saved the tty special chars at least once. */
|
||||
if (RL_ISSTATE(RL_STATE_TTYCSAVED) == 0)
|
||||
return;
|
||||
|
||||
RESET_SPECIAL (_rl_tty_chars.t_erase);
|
||||
RESET_SPECIAL (_rl_tty_chars.t_kill);
|
||||
|
||||
# if defined (VLNEXT) && defined (TERMIOS_TTY_DRIVER)
|
||||
RESET_SPECIAL (_rl_tty_chars.t_lnext);
|
||||
# endif /* VLNEXT && TERMIOS_TTY_DRIVER */
|
||||
|
||||
# if defined (VWERASE) && defined (TERMIOS_TTY_DRIVER)
|
||||
RESET_SPECIAL (_rl_tty_chars.t_werase);
|
||||
# endif /* VWERASE && TERMIOS_TTY_DRIVER */
|
||||
}
|
||||
|
||||
#if defined (HANDLE_SIGNALS)
|
||||
|
||||
#if defined (NEW_TTY_DRIVER)
|
||||
|
||||
+16
-16
@@ -61,22 +61,22 @@
|
||||
#endif /* !NEW_TTY_DRIVER && !_POSIX_VDISABLE */
|
||||
|
||||
typedef struct _rl_tty_chars {
|
||||
char t_eof;
|
||||
char t_eol;
|
||||
char t_eol2;
|
||||
char t_erase;
|
||||
char t_werase;
|
||||
char t_kill;
|
||||
char t_reprint;
|
||||
char t_intr;
|
||||
char t_quit;
|
||||
char t_susp;
|
||||
char t_dsusp;
|
||||
char t_start;
|
||||
char t_stop;
|
||||
char t_lnext;
|
||||
char t_flush;
|
||||
char t_status;
|
||||
unsigned char t_eof;
|
||||
unsigned char t_eol;
|
||||
unsigned char t_eol2;
|
||||
unsigned char t_erase;
|
||||
unsigned char t_werase;
|
||||
unsigned char t_kill;
|
||||
unsigned char t_reprint;
|
||||
unsigned char t_intr;
|
||||
unsigned char t_quit;
|
||||
unsigned char t_susp;
|
||||
unsigned char t_dsusp;
|
||||
unsigned char t_start;
|
||||
unsigned char t_stop;
|
||||
unsigned char t_lnext;
|
||||
unsigned char t_flush;
|
||||
unsigned char t_status;
|
||||
} _RL_TTY_CHARS;
|
||||
|
||||
#endif /* _RLTTY_H_ */
|
||||
|
||||
+11
-1
@@ -82,8 +82,13 @@ static void
|
||||
make_history_line_current (entry)
|
||||
HIST_ENTRY *entry;
|
||||
{
|
||||
rl_replace_line (entry->line, 0);
|
||||
#if 0
|
||||
rl_replace_line (entry->line, 1);
|
||||
rl_undo_list = (UNDO_LIST *)entry->data;
|
||||
#else
|
||||
_rl_replace_text (entry->line, 0, rl_end);
|
||||
_rl_fix_point (1);
|
||||
#endif
|
||||
|
||||
if (_rl_saved_line_for_history)
|
||||
_rl_free_history_entry (_rl_saved_line_for_history);
|
||||
@@ -189,6 +194,11 @@ noninc_search (dir, pchar)
|
||||
saved_point = rl_point;
|
||||
saved_mark = rl_mark;
|
||||
|
||||
/* Clear the undo list, since reading the search string should create its
|
||||
own undo list, and the whole list will end up being freed when we
|
||||
finish reading the search string. */
|
||||
rl_undo_list = 0;
|
||||
|
||||
/* Use the line buffer to read the search string. */
|
||||
rl_line_buffer[0] = 0;
|
||||
rl_end = rl_point = 0;
|
||||
|
||||
@@ -73,6 +73,10 @@ typedef struct { SigHandler *sa_handler; int sa_mask, sa_flags; } sighandler_cxt
|
||||
# define sigemptyset(m)
|
||||
#endif /* !HAVE_POSIX_SIGNALS */
|
||||
|
||||
#ifndef SA_RESTART
|
||||
# define SA_RESTART 0
|
||||
#endif
|
||||
|
||||
static SigHandler *rl_set_sighandler PARAMS((int, SigHandler *, sighandler_cxt *));
|
||||
static void rl_maybe_set_sighandler PARAMS((int, SigHandler *, sighandler_cxt *));
|
||||
|
||||
@@ -85,6 +89,8 @@ int rl_catch_signals = 1;
|
||||
/* If non-zero, readline will install a signal handler for SIGWINCH. */
|
||||
#ifdef SIGWINCH
|
||||
int rl_catch_sigwinch = 1;
|
||||
#else
|
||||
int rl_catch_sigwinch = 0; /* for the readline state struct in readline.c */
|
||||
#endif
|
||||
|
||||
static int signals_set_flag;
|
||||
@@ -233,7 +239,7 @@ rl_set_sighandler (sig, handler, ohandler)
|
||||
struct sigaction act;
|
||||
|
||||
act.sa_handler = handler;
|
||||
act.sa_flags = 0; /* XXX - should we set SA_RESTART for SIGWINCH? */
|
||||
act.sa_flags = (sig == SIGWINCH) ? SA_RESTART : 0;
|
||||
sigemptyset (&act.sa_mask);
|
||||
sigemptyset (&ohandler->sa_mask);
|
||||
sigaction (sig, &act, &old_handler);
|
||||
|
||||
+6
-10
@@ -347,11 +347,7 @@ get_term_capabilities (bp)
|
||||
register int i;
|
||||
|
||||
for (i = 0; i < NUM_TC_STRINGS; i++)
|
||||
# ifdef __LCC__
|
||||
*(tc_strings[i].tc_value) = tgetstr ((char *)tc_strings[i].tc_var, bp);
|
||||
# else
|
||||
*(tc_strings[i].tc_value) = tgetstr (tc_strings[i].tc_var, bp);
|
||||
# endif
|
||||
#endif
|
||||
tcap_initialized = 1;
|
||||
}
|
||||
@@ -489,13 +485,13 @@ bind_termcap_arrow_keys (map)
|
||||
xkeymap = _rl_keymap;
|
||||
_rl_keymap = map;
|
||||
|
||||
_rl_bind_if_unbound (_rl_term_ku, rl_get_previous_history);
|
||||
_rl_bind_if_unbound (_rl_term_kd, rl_get_next_history);
|
||||
_rl_bind_if_unbound (_rl_term_kr, rl_forward);
|
||||
_rl_bind_if_unbound (_rl_term_kl, rl_backward);
|
||||
rl_bind_keyseq_if_unbound (_rl_term_ku, rl_get_previous_history);
|
||||
rl_bind_keyseq_if_unbound (_rl_term_kd, rl_get_next_history);
|
||||
rl_bind_keyseq_if_unbound (_rl_term_kr, rl_forward_char);
|
||||
rl_bind_keyseq_if_unbound (_rl_term_kl, rl_backward_char);
|
||||
|
||||
_rl_bind_if_unbound (_rl_term_kh, rl_beg_of_line); /* Home */
|
||||
_rl_bind_if_unbound (_rl_term_at7, rl_end_of_line); /* End */
|
||||
rl_bind_keyseq_if_unbound (_rl_term_kh, rl_beg_of_line); /* Home */
|
||||
rl_bind_keyseq_if_unbound (_rl_term_at7, rl_end_of_line); /* End */
|
||||
|
||||
_rl_keymap = xkeymap;
|
||||
}
|
||||
|
||||
+15
-9
@@ -170,6 +170,9 @@ _rl_fix_point (fix_mark_too)
|
||||
}
|
||||
#undef _RL_FIX_POINT
|
||||
|
||||
/* Replace the contents of the line buffer between START and END with
|
||||
TEXT. The operation is undoable. To replace the entire line in an
|
||||
undoable mode, use _rl_replace_text(text, 0, rl_end); */
|
||||
int
|
||||
_rl_replace_text (text, start, end)
|
||||
const char *text;
|
||||
@@ -801,13 +804,10 @@ _rl_overwrite_char (count, c)
|
||||
k = _rl_read_mbstring (c, mbkey, MB_LEN_MAX);
|
||||
#endif
|
||||
|
||||
rl_begin_undo_group ();
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
rl_begin_undo_group ();
|
||||
|
||||
if (rl_point < rl_end)
|
||||
rl_delete (1, c);
|
||||
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
|
||||
rl_insert_text (mbkey);
|
||||
@@ -815,9 +815,12 @@ _rl_overwrite_char (count, c)
|
||||
#endif
|
||||
_rl_insert_char (1, c);
|
||||
|
||||
rl_end_undo_group ();
|
||||
if (rl_point < rl_end)
|
||||
rl_delete (1, c);
|
||||
}
|
||||
|
||||
rl_end_undo_group ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -935,9 +938,12 @@ _rl_overwrite_rubout (count, key)
|
||||
rl_delete_text (opoint, rl_point);
|
||||
|
||||
/* Emacs puts point at the beginning of the sequence of spaces. */
|
||||
opoint = rl_point;
|
||||
_rl_insert_char (l, ' ');
|
||||
rl_point = opoint;
|
||||
if (rl_point < rl_end)
|
||||
{
|
||||
opoint = rl_point;
|
||||
_rl_insert_char (l, ' ');
|
||||
rl_point = opoint;
|
||||
}
|
||||
|
||||
rl_end_undo_group ();
|
||||
|
||||
|
||||
+1
-1
@@ -250,7 +250,7 @@ _rl_strpbrk (string1, string2)
|
||||
{
|
||||
v = _rl_get_char_len (string1, &ps);
|
||||
if (v > 1)
|
||||
string += v - 1; /* -1 to account for auto-increment in loop */
|
||||
string1 += v - 1; /* -1 to account for auto-increment in loop */
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -640,7 +640,7 @@ _rl_vi_done_inserting ()
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_rl_vi_last_key_before_insert == 'i' && rl_undo_list)
|
||||
if ((_rl_vi_last_key_before_insert == 'i' || _rl_vi_last_key_before_insert == 'a') && rl_undo_list)
|
||||
_rl_vi_save_insert (rl_undo_list);
|
||||
/* XXX - Other keys probably need to be checked. */
|
||||
else if (_rl_vi_last_key_before_insert == 'C')
|
||||
@@ -680,7 +680,8 @@ _rl_vi_change_mbchar_case (count)
|
||||
int count;
|
||||
{
|
||||
wchar_t wc;
|
||||
char mb[MB_LEN_MAX];
|
||||
char mb[MB_LEN_MAX+1];
|
||||
int mblen;
|
||||
mbstate_t ps;
|
||||
|
||||
memset (&ps, 0, sizeof (mbstate_t));
|
||||
@@ -703,7 +704,9 @@ _rl_vi_change_mbchar_case (count)
|
||||
/* Vi is kind of strange here. */
|
||||
if (wc)
|
||||
{
|
||||
wctomb (mb, wc);
|
||||
mblen = wcrtomb (mb, wc, &ps);
|
||||
if (mblen >= 0)
|
||||
mb[mblen] = '\0';
|
||||
rl_begin_undo_group ();
|
||||
rl_delete (1, 0);
|
||||
rl_insert_text (mb);
|
||||
@@ -1315,7 +1318,7 @@ rl_vi_subst (count, key)
|
||||
{
|
||||
/* If we are redoing, rl_vi_change_to will stuff the last motion char */
|
||||
if (vi_redoing == 0)
|
||||
rl_stuff_char ((key == 'S') ? 'c' : ' '); /* `S' == `cc', `s' == `c ' */
|
||||
rl_stuff_char ((key == 'S') ? 'c' : 'l'); /* `S' == `cc', `s' == `cl' */
|
||||
|
||||
return (rl_vi_change_to (count, 'c'));
|
||||
}
|
||||
|
||||
+18
-14
@@ -71,8 +71,8 @@ CSOURCES = clktck.c clock.c getcwd.c getenv.c oslib.c setlinebuf.c \
|
||||
inet_aton.c netconn.c netopen.c strpbrk.c timeval.c makepath.c \
|
||||
pathcanon.c pathphys.c tmpfile.c stringlist.c stringvec.c spell.c \
|
||||
shquote.c strtrans.c strindex.c snprintf.c mailstat.c \
|
||||
fmtulong.c fmtullong.c fmtumax.c \
|
||||
strtoll.c strtoull.c strtoimax.c strtoumax.c memset.c \
|
||||
fmtulong.c fmtullong.c fmtumax.c shmatch.c \
|
||||
strtoll.c strtoull.c strtoimax.c strtoumax.c memset.c strstr.c \
|
||||
mktime.c strftime.c xstrchr.c zcatfd.c
|
||||
|
||||
# The header files for this library.
|
||||
@@ -81,7 +81,7 @@ HSOURCES =
|
||||
# The object files contained in $(LIBRARY_NAME)
|
||||
LIBOBJS = @LIBOBJS@
|
||||
OBJECTS = clktck.o clock.o getenv.o oslib.o setlinebuf.o \
|
||||
itos.o zread.o zwrite.o shtty.o \
|
||||
itos.o zread.o zwrite.o shtty.o shmatch.o \
|
||||
netconn.o netopen.o timeval.o makepath.o pathcanon.o \
|
||||
pathphys.o tmpfile.o stringlist.o stringvec.o spell.o shquote.o \
|
||||
strtrans.o strindex.o snprintf.o mailstat.o fmtulong.o \
|
||||
@@ -113,6 +113,9 @@ mostlyclean: clean
|
||||
|
||||
# Dependencies
|
||||
|
||||
${BUILD_DIR}/version.h: ${BUILD_DIR}/config.h ${BUILD_DIR}/Makefile Makefile
|
||||
-( cd ${BUILD_DIR} && ${MAKE} ${MFLAGS} version.h )
|
||||
|
||||
# rules for losing makes, like SunOS
|
||||
clktck.o: clktck.c
|
||||
clock.o: clock.c
|
||||
@@ -231,7 +234,8 @@ getenv.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topd
|
||||
getenv.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
|
||||
getenv.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
|
||||
getenv.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
|
||||
getenv.o: ${topdir}/pathnames.h ${topdir}/externs.h
|
||||
getenv.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
|
||||
getenv.o: ${BUILD_DIR}/version.h
|
||||
|
||||
inet_aton.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
|
||||
inet_aton.o: ${BASHINCDIR}/stdc.h
|
||||
@@ -243,7 +247,7 @@ itos.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdir
|
||||
itos.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
|
||||
itos.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
|
||||
itos.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
|
||||
itos.o: ${topdir}/pathnames.h ${topdir}/externs.h
|
||||
itos.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
|
||||
|
||||
makepath.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
|
||||
makepath.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
|
||||
@@ -252,7 +256,7 @@ makepath.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${to
|
||||
makepath.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
|
||||
makepath.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
|
||||
makepath.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
|
||||
makepath.o: ${topdir}/pathnames.h ${topdir}/externs.h
|
||||
makepath.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
|
||||
|
||||
netconn.o: ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/filecntl.h
|
||||
netconn.o: ${topdir}/bashtypes.h
|
||||
@@ -264,7 +268,7 @@ netopen.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${top
|
||||
netopen.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
|
||||
netopen.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
|
||||
netopen.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
|
||||
netopen.o: ${topdir}/pathnames.h ${topdir}/externs.h
|
||||
netopen.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
|
||||
|
||||
oslib.o: ${topdir}/bashtypes.h ${topdir}/bashansi.h ${BASHINCDIR}/maxpath.h
|
||||
oslib.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
|
||||
@@ -273,7 +277,7 @@ oslib.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdi
|
||||
oslib.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
|
||||
oslib.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
|
||||
oslib.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
|
||||
oslib.o: ${topdir}/pathnames.h ${topdir}/externs.h
|
||||
oslib.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
|
||||
oslib.o: ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/filecntl.h
|
||||
oslib.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
|
||||
|
||||
@@ -284,7 +288,7 @@ pathcanon.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${t
|
||||
pathcanon.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
|
||||
pathcanon.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
|
||||
pathcanon.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
|
||||
pathcanon.o: ${topdir}/pathnames.h ${topdir}/externs.h
|
||||
pathcanon.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
|
||||
pathcanon.o: ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/filecntl.h
|
||||
pathcanon.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
|
||||
|
||||
@@ -295,7 +299,7 @@ pathphys.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${to
|
||||
pathphys.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
|
||||
pathphys.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
|
||||
pathphys.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
|
||||
pathphys.o: ${topdir}/pathnames.h ${topdir}/externs.h
|
||||
pathphys.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
|
||||
pathphys.o: ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/filecntl.h
|
||||
pathphys.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
|
||||
|
||||
@@ -329,7 +333,7 @@ strerror.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${to
|
||||
strerror.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
|
||||
strerror.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
|
||||
strerror.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
|
||||
strerror.o: ${topdir}/pathnames.h ${topdir}/externs.h
|
||||
strerror.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
|
||||
|
||||
strindex.o: ${BASHINCDIR}/stdc.h ${topdir}/bashansi.h
|
||||
strindex.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
|
||||
@@ -341,7 +345,7 @@ stringlist.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${
|
||||
stringlist.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
|
||||
stringlist.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
|
||||
stringlist.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
|
||||
stringlist.o: ${topdir}/pathnames.h ${topdir}/externs.h
|
||||
stringlist.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
|
||||
|
||||
stringvec.o: ${topdir}/bashansi.h ${BASHINCDIR}/chartypes.h
|
||||
stringvec.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
|
||||
@@ -350,7 +354,7 @@ stringvec.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${t
|
||||
stringvec.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
|
||||
stringvec.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
|
||||
stringvec.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
|
||||
stringvec.o: ${topdir}/pathnames.h ${topdir}/externs.h
|
||||
stringvec.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
|
||||
|
||||
strpbrk.o: ${BASHINCDIR}/stdc.h
|
||||
|
||||
@@ -385,7 +389,7 @@ strtrans.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${to
|
||||
strtrans.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
|
||||
strtrans.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
|
||||
strtrans.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
|
||||
strtrans.o: ${topdir}/pathnames.h ${topdir}/externs.h
|
||||
strtrans.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
|
||||
|
||||
times.o: ${BASHINCDIR}/systimes.h
|
||||
times.o: ${BASHINCDIR}/posixtime.h
|
||||
|
||||
@@ -38,6 +38,9 @@
|
||||
#ifdef HAVE_STDINT_H
|
||||
# include <stdint.h>
|
||||
#endif
|
||||
#ifdef HAVE_INTTYPES_H
|
||||
# include <inttypes.h>
|
||||
#endif
|
||||
#include <chartypes.h>
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
+1
-1
@@ -169,7 +169,7 @@ setenv (name, value, rewrite)
|
||||
}
|
||||
|
||||
var = 0;
|
||||
v = value;
|
||||
v = (char *)value; /* some compilers need explicit cast */
|
||||
/* XXX - should we worry about readonly here? */
|
||||
if (rewrite == 0)
|
||||
var = find_variable (name);
|
||||
|
||||
+1
-1
@@ -149,7 +149,7 @@ mailstat(path, st)
|
||||
closedir(dd);
|
||||
}
|
||||
|
||||
if (atime)
|
||||
/* if (atime) */ /* Set atime even if cur/ is empty */
|
||||
st_ret.st_atime = atime;
|
||||
if (mtime)
|
||||
st_ret.st_mtime = mtime;
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@
|
||||
#include <config.h>
|
||||
|
||||
#include <bashtypes.h>
|
||||
#ifndef _MINIX
|
||||
#if ! defined(_MINIX) && defined (HAVE_SYS_FILE_H)
|
||||
# include <sys/file.h>
|
||||
#endif
|
||||
#include <posixstat.h>
|
||||
|
||||
+42
-4
@@ -68,7 +68,7 @@ _path_readlink (path, buf, bufsiz)
|
||||
|
||||
/*
|
||||
* Return PATH with all symlinks expanded in newly-allocated memory.
|
||||
* This always gets a full pathname.
|
||||
* This always gets an absolute pathname.
|
||||
*/
|
||||
|
||||
char *
|
||||
@@ -80,11 +80,26 @@ sh_physpath (path, flags)
|
||||
char *result, *p, *q, *qsave, *qbase, *workpath;
|
||||
int double_slash_path, linklen, nlink;
|
||||
|
||||
/* First sanity check -- punt immediately if the name is too long. */
|
||||
linklen = strlen (path);
|
||||
|
||||
#if 0
|
||||
if (linklen >= PATH_MAX)
|
||||
return (savestring (path));
|
||||
#endif
|
||||
|
||||
nlink = 0;
|
||||
q = result = (char *)xmalloc (PATH_MAX + 1);
|
||||
|
||||
workpath = (char *)xmalloc (PATH_MAX + 1);
|
||||
strcpy (workpath, path);
|
||||
/* Even if we get something longer than PATH_MAX, we might be able to
|
||||
shorten it, so we try. */
|
||||
if (linklen >= PATH_MAX)
|
||||
workpath = savestring (path);
|
||||
else
|
||||
{
|
||||
workpath = (char *)xmalloc (PATH_MAX + 1);
|
||||
strcpy (workpath, path);
|
||||
}
|
||||
|
||||
/* This always gets an absolute pathname. */
|
||||
|
||||
@@ -133,7 +148,19 @@ sh_physpath (path, flags)
|
||||
if (q != qbase)
|
||||
*q++ = DIRSEP;
|
||||
while (*p && (ISDIRSEP(*p) == 0))
|
||||
*q++ = *p++;
|
||||
{
|
||||
if (q - result >= PATH_MAX)
|
||||
{
|
||||
#ifdef ENAMETOOLONG
|
||||
errno = ENAMETOOLONG;
|
||||
#else
|
||||
errno = EINVAL;
|
||||
#endif
|
||||
goto error;
|
||||
}
|
||||
|
||||
*q++ = *p++;
|
||||
}
|
||||
|
||||
*q = '\0';
|
||||
|
||||
@@ -160,6 +187,17 @@ error:
|
||||
|
||||
linkbuf[linklen] = '\0';
|
||||
|
||||
/* If the new path length would overrun PATH_MAX, punt now. */
|
||||
if ((strlen (p) + linklen + 2) >= PATH_MAX)
|
||||
{
|
||||
#ifdef ENAMETOOLONG
|
||||
errno = ENAMETOOLONG;
|
||||
#else
|
||||
errno = EINVAL;
|
||||
#endif
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Form the new pathname by copying the link value to a temporary
|
||||
buffer and appending the rest of `workpath'. Reset p to point
|
||||
to the start of the rest of the path. If the link value is an
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
/* Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
Bash is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation; either version 2, or (at your option) any later
|
||||
version.
|
||||
|
||||
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with Bash; see the file COPYING. If not, write to the Free Software
|
||||
Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
|
||||
|
||||
/*
|
||||
* shmatch.c -- shell interface to posix regular expression matching.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_POSIX_REGEXP)
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "bashansi.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <regex.h>
|
||||
|
||||
#include "shell.h"
|
||||
#include "variables.h"
|
||||
#include "externs.h"
|
||||
|
||||
extern int glob_ignore_case;
|
||||
|
||||
int
|
||||
sh_regmatch (string, pattern, flags)
|
||||
const char *string;
|
||||
const char *pattern;
|
||||
int flags;
|
||||
{
|
||||
regex_t regex = { 0 };
|
||||
regmatch_t *matches;
|
||||
int rflags;
|
||||
#if defined (ARRAY_VARS)
|
||||
SHELL_VAR *rematch;
|
||||
ARRAY *amatch;
|
||||
int subexp_ind;
|
||||
char *subexp_str;
|
||||
int subexp_len;
|
||||
#endif
|
||||
int result;
|
||||
|
||||
|
||||
rematch = (SHELL_VAR *)NULL;
|
||||
|
||||
rflags = REG_EXTENDED;
|
||||
if (glob_ignore_case)
|
||||
rflags |= REG_ICASE;
|
||||
#if !defined (ARRAY_VARS)
|
||||
rflags |= REG_NOSUB;
|
||||
#endif
|
||||
|
||||
if (regcomp (®ex, pattern, rflags))
|
||||
return 2; /* flag for printing a warning here. */
|
||||
|
||||
#if defined (ARRAY_VARS)
|
||||
matches = (regmatch_t *)malloc (sizeof (regmatch_t) * (regex.re_nsub + 1));
|
||||
#else
|
||||
matches = NULL;
|
||||
#endif
|
||||
|
||||
if (regexec (®ex, string, regex.re_nsub + 1, matches, 0))
|
||||
result = EXECUTION_FAILURE;
|
||||
else
|
||||
result = EXECUTION_SUCCESS; /* match */
|
||||
|
||||
#if defined (ARRAY_VARS)
|
||||
subexp_len = strlen (string) + 10;
|
||||
subexp_str = malloc (subexp_len + 1);
|
||||
|
||||
/* Store the parenthesized subexpressions in the array BASH_REMATCH.
|
||||
Element 0 is the portion that matched the entire regexp. Element 1
|
||||
is the part that matched the first subexpression, and so on. */
|
||||
unbind_variable ("BASH_REMATCH");
|
||||
rematch = make_new_array_variable ("BASH_REMATCH");
|
||||
amatch = array_cell (rematch);
|
||||
|
||||
if ((flags & SHMAT_SUBEXP) && result == EXECUTION_SUCCESS && subexp_str)
|
||||
{
|
||||
for (subexp_ind = 0; subexp_ind <= regex.re_nsub; subexp_ind++)
|
||||
{
|
||||
memset (subexp_str, 0, subexp_len);
|
||||
strncpy (subexp_str, string + matches[subexp_ind].rm_so,
|
||||
matches[subexp_ind].rm_eo - matches[subexp_ind].rm_so);
|
||||
array_insert (amatch, subexp_ind, subexp_str);
|
||||
}
|
||||
}
|
||||
|
||||
VSETATTR (rematch, att_readonly);
|
||||
|
||||
free (subexp_str);
|
||||
free (matches);
|
||||
#endif /* ARRAY_VARS */
|
||||
|
||||
regfree (®ex);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif /* HAVE_POSIX_REGEXP */
|
||||
+12
-1
@@ -83,6 +83,8 @@ sh_double_quote (string)
|
||||
{
|
||||
if (sh_syntaxtab[c] & CBSDQUOTE)
|
||||
*r++ = '\\';
|
||||
else if (c == CTLESC || c == CTLNUL)
|
||||
*r++ = CTLESC; /* could be '\\'? */
|
||||
|
||||
*r++ = c;
|
||||
}
|
||||
@@ -94,7 +96,8 @@ sh_double_quote (string)
|
||||
}
|
||||
|
||||
/* Remove backslashes that are quoting characters that are special between
|
||||
double quotes. Return a new string. */
|
||||
double quotes. Return a new string. XXX - should this handle CTLESC
|
||||
and CTLNUL? */
|
||||
char *
|
||||
sh_un_double_quote (string)
|
||||
char *string;
|
||||
@@ -158,6 +161,11 @@ sh_backslash_quote (string)
|
||||
*r++ = c;
|
||||
break;
|
||||
#endif
|
||||
case CTLESC: case CTLNUL: /* internal quoting characters */
|
||||
*r++ = CTLESC; /* could be '\\'? */
|
||||
*r++ = c;
|
||||
break;
|
||||
|
||||
case '#': /* comment char */
|
||||
if (s == string)
|
||||
*r++ = '\\';
|
||||
@@ -188,6 +196,9 @@ sh_backslash_quote_for_double_quotes (string)
|
||||
{
|
||||
if (sh_syntaxtab[c] & CBSDQUOTE)
|
||||
*r++ = '\\';
|
||||
/* I should probably add flags for these to sh_syntaxtab[] */
|
||||
else if (c == CTLESC || c == CTLNUL)
|
||||
*r++ = CTLESC; /* could be '\\'? */
|
||||
|
||||
*r++ = c;
|
||||
}
|
||||
|
||||
+5
-4
@@ -45,10 +45,11 @@
|
||||
|
||||
/*
|
||||
* Currently doesn't handle (and bash/readline doesn't use):
|
||||
* *M$ width, precision specifications
|
||||
* %N$ numbered argument conversions
|
||||
* inf, nan floating values imperfect (if isinf(), isnan() not in libc)
|
||||
* support for `F' is imperfect, since underlying printf may not handle it
|
||||
* * *M$ width, precision specifications
|
||||
* * %N$ numbered argument conversions
|
||||
* * inf, nan floating values imperfect (if isinf(), isnan() not in libc)
|
||||
* * support for `F' is imperfect with ldfallback(), since underlying
|
||||
* printf may not handle it -- should ideally have another autoconf test
|
||||
*/
|
||||
|
||||
#define FLOATING_POINT
|
||||
|
||||
+122
@@ -0,0 +1,122 @@
|
||||
/* Copyright (C) 1994, 1999 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
/*
|
||||
* My personal strstr() implementation that beats most other algorithms.
|
||||
* Until someone tells me otherwise, I assume that this is the
|
||||
* fastest implementation of strstr() in C.
|
||||
* I deliberately chose not to comment it. You should have at least
|
||||
* as much fun trying to understand it, as I had to write it :-).
|
||||
*
|
||||
* Stephen R. van den Berg, berg@pool.informatik.rwth-aachen.de */
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#if defined _LIBC || defined HAVE_STRING_H
|
||||
# include <string.h>
|
||||
#endif
|
||||
#include <sys/types.h>
|
||||
|
||||
typedef unsigned chartype;
|
||||
|
||||
#undef strstr
|
||||
|
||||
char *
|
||||
strstr (const char *phaystack, const char *pneedle)
|
||||
{
|
||||
register const unsigned char *haystack, *needle;
|
||||
register chartype b, c;
|
||||
|
||||
haystack = (const unsigned char *) phaystack;
|
||||
needle = (const unsigned char *) pneedle;
|
||||
|
||||
b = *needle;
|
||||
if (b != '\0')
|
||||
{
|
||||
haystack--; /* possible ANSI violation */
|
||||
do
|
||||
{
|
||||
c = *++haystack;
|
||||
if (c == '\0')
|
||||
goto ret0;
|
||||
}
|
||||
while (c != b);
|
||||
|
||||
c = *++needle;
|
||||
if (c == '\0')
|
||||
goto foundneedle;
|
||||
++needle;
|
||||
goto jin;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
register chartype a;
|
||||
register const unsigned char *rhaystack, *rneedle;
|
||||
|
||||
do
|
||||
{
|
||||
a = *++haystack;
|
||||
if (a == '\0')
|
||||
goto ret0;
|
||||
if (a == b)
|
||||
break;
|
||||
a = *++haystack;
|
||||
if (a == '\0')
|
||||
goto ret0;
|
||||
shloop:; }
|
||||
while (a != b);
|
||||
|
||||
jin: a = *++haystack;
|
||||
if (a == '\0')
|
||||
goto ret0;
|
||||
|
||||
if (a != c)
|
||||
goto shloop;
|
||||
|
||||
rhaystack = haystack-- + 1;
|
||||
rneedle = needle;
|
||||
a = *rneedle;
|
||||
|
||||
if (*rhaystack == a)
|
||||
do
|
||||
{
|
||||
if (a == '\0')
|
||||
goto foundneedle;
|
||||
++rhaystack;
|
||||
a = *++needle;
|
||||
if (*rhaystack != a)
|
||||
break;
|
||||
if (a == '\0')
|
||||
goto foundneedle;
|
||||
++rhaystack;
|
||||
a = *++needle;
|
||||
}
|
||||
while (*rhaystack == a);
|
||||
|
||||
needle = rneedle; /* took the register-poor approach */
|
||||
|
||||
if (a == '\0')
|
||||
break;
|
||||
}
|
||||
}
|
||||
foundneedle:
|
||||
return (char*) haystack;
|
||||
ret0:
|
||||
return 0;
|
||||
}
|
||||
+18
-1
@@ -92,10 +92,27 @@ ansicstr (string, len, flags, sawc, rlen)
|
||||
c &= 0xFF;
|
||||
break;
|
||||
case 'x': /* Hex digit -- non-ANSI */
|
||||
if ((flags & 2) && *s == '{')
|
||||
{
|
||||
flags |= 16; /* internal flag value */
|
||||
s++;
|
||||
}
|
||||
/* Consume at least two hex characters */
|
||||
for (temp = 2, c = 0; ISXDIGIT ((unsigned char)*s) && temp--; s++)
|
||||
c = (c * 16) + HEXVALUE (*s);
|
||||
/* DGK says that after a `\x{' ksh93 consumes ISXDIGIT chars
|
||||
until a non-xdigit or `}', so potentially more than two
|
||||
chars are consumed. */
|
||||
if (flags & 16)
|
||||
{
|
||||
for ( ; ISXDIGIT ((unsigned char)*s); s++)
|
||||
c = (c * 16) + HEXVALUE (*s);
|
||||
flags &= ~16;
|
||||
if (*s == '}')
|
||||
s++;
|
||||
}
|
||||
/* \x followed by non-hex digits is passed through unchanged */
|
||||
if (temp == 2)
|
||||
else if (temp == 2)
|
||||
{
|
||||
*r++ = '\\';
|
||||
c = 'x';
|
||||
|
||||
@@ -21,8 +21,8 @@ Free Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
|
||||
#include <config.h>
|
||||
|
||||
/* Get the O_* definitions for open et al. */
|
||||
#ifndef _MINIX
|
||||
#include <sys/file.h>
|
||||
#if !defined (_MINIX) && defined (HAVE_SYS_FILE_H)
|
||||
# include <sys/file.h>
|
||||
#endif
|
||||
|
||||
#include <fcntl.h>
|
||||
|
||||
Reference in New Issue
Block a user