commit bash-20110720 snapshot

This commit is contained in:
Chet Ramey
2012-01-09 08:24:22 -05:00
parent 9efb1fb32f
commit 19baff85a2
31 changed files with 28471 additions and 56 deletions
+88
View File
@@ -11974,3 +11974,91 @@ lib/readline/isearch.c
- _rl_isearch_dispatch: when adding character to search string, use
cxt->lastc (which we use in the switch statement) instead of c,
since lastc can be modified earlier in the function
7/18
----
lib/readline/rlprivate.h
- _rl_search_context: add another member to save previous value of
(multibyte) lastc: pmb is to mb as prevc is to lastc
lib/readline/isearch.c:
- _rl_isearch_dispatch: if a key sequence indexes into a new keymap,
but doesn't find any bound function (k[ind].function == 0) or is
bound to self-insert (k[ind].function == rl_insert), back up and
insert the previous character (the one that caused the index into a
new keymap) and arrange things so the current character is the next
one read, so both of them end up in the search string. Fixes bug
reported by Clark Wang <dearvoid@gmail.com>
- _rl_isearch_dispatch: a couple of efficiency improvements when adding
characters to the isearch string
7/24
----
lib/readline/isearch.c
- _rl_isearch_dispatch: save and restore cxt->mb and cxt->pmb
appropriately when in a multibyte locale
doc/{bash.1,bashref.texi}
- correct description of {x}>file (and other redirection operators
that allocate a file descriptor) to note the the fd range is
greater than or equal to 10. Fixes problem reported by
Christian Ullrich
lib/readline/signals.c
- rl_signal_handler: don't interrupt immediately if in callback mode
lib/readline/callback.c
- rl_callback_read_char: install signal handlers only when readline
has control in callback mode, so readline's signal handlers aren't
called when the application is active (e.g., between the calls to
rl_callback_handler_install and rl_callback_read_char). If the
readline signal handlers only set a flag, which the application
doesn't know about, the signals will effectively be ignored until
the next time the application calls into the readline callback
interface. Fixes problem of calling unsafe functions from signal
handlers when in callback mode reported by Jan Kratochvil
<jan.kratochvil@redhat.com>
execute_cmd.c
- fix_assignment_words: when in Posix mode, the `command' builtin
doesn't change whether or not the command name it protects is an
assignment builtin. One or more instances of `command'
preceding `export', for instance, doesn't make `export' treat its
assignment statement arguments differently. Posix interpretation
#351
doc/{bash.1,bashref.texi}
- document new Posix-mode behavior of `command' when preceding builtins
that take assignment statements as arguments
builtins/printf.def
- printstr: if fieldwidth or precision are < 0 or > INT_MAX when
supplied explicitly (since we take care of the `-' separately),
clamp at INT_MAX like when using getint(). Fixes issue reported
by Ralph Coredroy <ralph@inputplus.co.uk>
7/25
----
lib/readline/chardefs.h
- isxdigit: don't define if compiling with c++; declared as a c++
template function. Fixes bug reported by Miroslav Lichvar
<mlichvar@redhat.com>
builtins/printf.def
- getint: if garglist == 0, return whatever getintmax returns (0).
Fixes bug reported by Ralph Coredroy <ralph@inputplus.co.uk>
7/28
----
doc/{bash.1,bashref.texi}
- minor changes to the descriptions of the cd and pushd builtins
lib/sh/zread.c
- zsyncfd: change variable holding return value from lseek to
off_t. Bug report and fix from Gregory Margo <gmargo@pacbell.net>
8/1
---
expr.c
- don't check for division by 0 when in a context where no evaluation
is taking place. Fixes bug reported by dnade.ext@orange-ftgroup.com
+133
View File
@@ -11846,6 +11846,10 @@ builtins/read.def
and set LINES and COLUMNS after a foreground job exits. From a
suggestion by Leslie Rhorer <lrhorer@satx.rr.com>
doc/{bash.1,bashref.texi}
- checkwinsize: remove language saying that only interactive shells
check the window size after each command
lib/readline/histfile.c
- history_backupfile: new file, creates a backup history file name
given a filename (appending `-')
@@ -11923,3 +11927,132 @@ lib/readline/complete.c
lib/readline/signals.c
- rl_signal_handler: if we're in callback mode, don't interrupt
immediately on a SIGWINCH
7/3
---
bashline.c
- set_directory_hook: and its siblings are a new set of functions to
set, save, and restore the appropriate directory completion hook
- change callers to use {set,save,restore}_directory_hook instead of
manipulating rl_directory_rewrite_hook directly
- dircomplete_expand: new variable, defaults to 0, if non-zero causes
directory names to be word-expanded during word and filename
completion
- change {set,save,restore}_directory_hook to look at dircomplete_expand
and change rl_directory_completion_hook or rl_directory_rewrite_hook
appropriately
bashline.h
- extern declaration for set_directory_hook so shopt code can use it
7/6
---
builtins/shopt.def
- globasciiranges: new settable shopt option, makes glob ranges act
as if in the C locale (so b no longer comes between A and B).
Suggested by Aharon Robbins <arnold@skeeve.com>
7/7
---
doc/{bash.1,bashref.texi}
- document new `globasciiranges' shopt option
7/8
---
builtins/shopt.def
- direxpand: new settable option, makes filename completion expand
variables in directory names like bash-4.1 did.
- shopt_set_complete_direxpand: new function, does the work for the
above by calling set_directory_hook
doc/{bash.1,bashref.texi}
- document new `direxpand' shopt option
7/15
----
lib/readline/isearch.c
- _rl_isearch_dispatch: when adding character to search string, use
cxt->lastc (which we use in the switch statement) instead of c,
since lastc can be modified earlier in the function
7/18
----
lib/readline/rlprivate.h
- _rl_search_context: add another member to save previous value of
(multibyte) lastc: pmb is to mb as prevc is to lastc
lib/readline/isearch.c:
- _rl_isearch_dispatch: if a key sequence indexes into a new keymap,
but doesn't find any bound function (k[ind].function == 0) or is
bound to self-insert (k[ind].function == rl_insert), back up and
insert the previous character (the one that caused the index into a
new keymap) and arrange things so the current character is the next
one read, so both of them end up in the search string. Fixes bug
reported by Clark Wang <dearvoid@gmail.com>
- _rl_isearch_dispatch: a couple of efficiency improvements when adding
characters to the isearch string
7/24
----
lib/readline/isearch.c
- _rl_isearch_dispatch: save and restore cxt->mb and cxt->pmb
appropriately when in a multibyte locale
doc/{bash.1,bashref.texi}
- correct description of {x}>file (and other redirection operators
that allocate a file descriptor) to note the the fd range is
greater than or equal to 10. Fixes problem reported by
Christian Ullrich
lib/readline/signals.c
- rl_signal_handler: don't interrupt immediately if in callback mode
lib/readline/callback.c
- rl_callback_read_char: install signal handlers only when readline
has control in callback mode, so readline's signal handlers aren't
called when the application is active (e.g., between the calls to
rl_callback_handler_install and rl_callback_read_char). If the
readline signal handlers only set a flag, which the application
doesn't know about, the signals will effectively be ignored until
the next time the application calls into the readline callback
interface. Fixes problem of calling unsafe functions from signal
handlers when in callback mode reported by Jan Kratochvil
<jan.kratochvil@redhat.com>
execute_cmd.c
- fix_assignment_words: when in Posix mode, the `command' builtin
doesn't change whether or not the command name it protects is an
assignment builtin. One or more instances of `command'
preceding `export', for instance, doesn't make `export' treat its
assignment statement arguments differently. Posix interpretation
#351
doc/{bash.1,bashref.texi}
- document new Posix-mode behavior of `command' when preceding builtins
that take assignment statements as arguments
builtins/printf.def
- printstr: if fieldwidth or precision are < 0 or > INT_MAX when
supplied explicitly (since we take care of the `-' separately),
clamp at INT_MAX like when using getint(). Fixes issue reported
by Ralph Coredroy <ralph@inputplus.co.uk>
7/25
----
lib/readline/chardefs.h
- isxdigit: don't define if compiling with c++; declared as a c++
template function. Fixes bug reported by Miroslav Lichvar
<mlichvar@redhat.com>
builtins/printf.def
- getint: if garglist == 0, return whatever getintmax returns (0).
Fixes bug reported by Ralph Coredroy <ralph@inputplus.co.uk>
7/28
----
doc/{bash.1,bashref.texi}
- minor changes to the descriptions of the cd and pushd builtins
lib/sh/zread.c
- zsyncfd: change variable holding return value from lseek to
off_t. Bug report and fix from Gregory Margo <gmargo@pacbell.net>
+2 -1
View File
@@ -290,7 +290,8 @@ cd_builtin (list)
free (temp);
}
#if 0 /* changed for bash-4.2 Posix cd description steps 5-6 */
#if 0
/* changed for bash-4.2 Posix cd description steps 5-6 */
/* POSIX.2 says that if `.' does not appear in $CDPATH, we don't
try the current directory, so we just punt now with an error
message if POSIXLY_CORRECT is non-zero. The check for cdpath[0]
+536
View File
@@ -0,0 +1,536 @@
This file is cd.def, from which is created cd.c. It implements the
builtins "cd" and "pwd" in Bash.
Copyright (C) 1987-2010 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 3 of the License, 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. If not, see <http://www.gnu.org/licenses/>.
$PRODUCES cd.c
#include <config.h>
#if defined (HAVE_UNISTD_H)
# ifdef _MINIX
# include <sys/types.h>
# endif
# include <unistd.h>
#endif
#include "../bashtypes.h"
#include "posixdir.h"
#include "posixstat.h"
#ifndef _MINIX
#include <sys/param.h>
#endif
#include <stdio.h>
#include "../bashansi.h"
#include "../bashintl.h"
#include <errno.h>
#include <tilde/tilde.h>
#include "../shell.h"
#include "../flags.h"
#include "maxpath.h"
#include "common.h"
#include "bashgetopt.h"
#if !defined (errno)
extern int errno;
#endif /* !errno */
extern int posixly_correct;
extern int array_needs_making;
extern const char * const bash_getcwd_errstr;
static int bindpwd __P((int));
static int setpwd __P((char *));
static char *resetpwd __P((char *));
static int change_to_directory __P((char *, int));
/* Change this to 1 to get cd spelling correction by default. */
int cdspelling = 0;
int cdable_vars;
static int eflag; /* file scope so bindpwd() can see it */
$BUILTIN cd
$FUNCTION cd_builtin
$SHORT_DOC cd [-L|[-P [-e]]] [dir]
Change the shell working directory.
Change the current directory to DIR. The default DIR is the value of the
HOME shell variable.
The variable CDPATH defines the search path for the directory containing
DIR. Alternative directory names in CDPATH are separated by a colon (:).
A null directory name is the same as the current directory. If DIR begins
with a slash (/), then CDPATH is not used.
If the directory is not found, and the shell option `cdable_vars' is set,
the word is assumed to be a variable name. If that variable has a value,
its value is used for DIR.
Options:
-L force symbolic links to be followed
-P use the physical directory structure without following symbolic
links
-e if the -P option is supplied, and the current working directory
cannot be determined successfully, exit with a non-zero status
The default is to follow symbolic links, as if `-L' were specified.
Exit Status:
Returns 0 if the directory is changed, and if $PWD is set successfully when
-P is used; non-zero otherwise.
$END
/* Just set $PWD, don't change OLDPWD. Used by `pwd -P' in posix mode. */
static int
setpwd (dirname)
char *dirname;
{
int old_anm;
SHELL_VAR *tvar;
old_anm = array_needs_making;
tvar = bind_variable ("PWD", dirname ? dirname : "", 0);
if (tvar && readonly_p (tvar))
return EXECUTION_FAILURE;
if (tvar && old_anm == 0 && array_needs_making && exported_p (tvar))
{
update_export_env_inplace ("PWD=", 4, dirname ? dirname : "");
array_needs_making = 0;
}
return EXECUTION_SUCCESS;
}
static int
bindpwd (no_symlinks)
int no_symlinks;
{
char *dirname, *pwdvar;
int old_anm, r;
SHELL_VAR *tvar;
r = sh_chkwrite (EXECUTION_SUCCESS);
#define tcwd the_current_working_directory
dirname = tcwd ? (no_symlinks ? sh_physpath (tcwd, 0) : tcwd)
: get_working_directory ("cd");
#undef tcwd
old_anm = array_needs_making;
pwdvar = get_string_value ("PWD");
tvar = bind_variable ("OLDPWD", pwdvar, 0);
if (tvar && readonly_p (tvar))
r = EXECUTION_FAILURE;
if (old_anm == 0 && array_needs_making && exported_p (tvar))
{
update_export_env_inplace ("OLDPWD=", 7, pwdvar);
array_needs_making = 0;
}
if (setpwd (dirname) == EXECUTION_FAILURE)
r = EXECUTION_FAILURE;
if (dirname == 0 && eflag)
r = EXECUTION_FAILURE;
if (dirname && dirname != the_current_working_directory)
free (dirname);
return (r);
}
/* Call get_working_directory to reset the value of
the_current_working_directory () */
static char *
resetpwd (caller)
char *caller;
{
char *tdir;
FREE (the_current_working_directory);
the_current_working_directory = (char *)NULL;
tdir = get_working_directory (caller);
return (tdir);
}
#define LCD_DOVARS 0x001
#define LCD_DOSPELL 0x002
#define LCD_PRINTPATH 0x004
#define LCD_FREEDIRNAME 0x008
/* This builtin is ultimately the way that all user-visible commands should
change the current working directory. It is called by cd_to_string (),
so the programming interface is simple, and it handles errors and
restrictions properly. */
int
cd_builtin (list)
WORD_LIST *list;
{
char *dirname, *cdpath, *path, *temp;
int path_index, no_symlinks, opt, lflag;
#if defined (RESTRICTED_SHELL)
if (restricted)
{
sh_restricted ((char *)NULL);
return (EXECUTION_FAILURE);
}
#endif /* RESTRICTED_SHELL */
eflag = 0;
no_symlinks = no_symbolic_links;
reset_internal_getopt ();
while ((opt = internal_getopt (list, "LP")) != -1)
{
switch (opt)
{
case 'P':
no_symlinks = 1;
break;
case 'L':
no_symlinks = 0;
break;
case 'e':
eflag = 1;
break;
default:
builtin_usage ();
return (EXECUTION_FAILURE);
}
}
list = loptend;
lflag = (cdable_vars ? LCD_DOVARS : 0) |
((interactive && cdspelling) ? LCD_DOSPELL : 0);
if (eflag && no_symlinks == 0)
eflag = 0;
if (list == 0)
{
/* `cd' without arguments is equivalent to `cd $HOME' */
dirname = get_string_value ("HOME");
if (dirname == 0)
{
builtin_error (_("HOME not set"));
return (EXECUTION_FAILURE);
}
lflag = 0;
}
else if (list->word->word[0] == '-' && list->word->word[1] == '\0')
{
/* This is `cd -', equivalent to `cd $OLDPWD' */
dirname = get_string_value ("OLDPWD");
if (dirname == 0)
{
builtin_error (_("OLDPWD not set"));
return (EXECUTION_FAILURE);
}
#if 0
lflag = interactive ? LCD_PRINTPATH : 0;
#else
lflag = LCD_PRINTPATH; /* According to SUSv3 */
#endif
}
else if (absolute_pathname (list->word->word))
dirname = list->word->word;
else if (privileged_mode == 0 && (cdpath = get_string_value ("CDPATH")))
{
dirname = list->word->word;
/* Find directory in $CDPATH. */
path_index = 0;
while (path = extract_colon_unit (cdpath, &path_index))
{
/* OPT is 1 if the path element is non-empty */
opt = path[0] != '\0';
temp = sh_makepath (path, dirname, MP_DOTILDE);
free (path);
if (change_to_directory (temp, no_symlinks))
{
/* POSIX.2 says that if a nonempty directory from CDPATH
is used to find the directory to change to, the new
directory name is echoed to stdout, whether or not
the shell is interactive. */
if (opt && (path = no_symlinks ? temp : the_current_working_directory))
printf ("%s\n", path);
free (temp);
#if 0
/* Posix.2 says that after using CDPATH, the resultant
value of $PWD will not contain `.' or `..'. */
return (bindpwd (posixly_correct || no_symlinks));
#else
return (bindpwd (no_symlinks));
#endif
}
else
free (temp);
}
#if 0 /* changed for bash-4.2 Posix cd description steps 5-6 */
/* POSIX.2 says that if `.' does not appear in $CDPATH, we don't
try the current directory, so we just punt now with an error
message if POSIXLY_CORRECT is non-zero. The check for cdpath[0]
is so we don't mistakenly treat a CDPATH value of "" as not
specifying the current directory. */
if (posixly_correct && cdpath[0])
{
builtin_error ("%s: %s", dirname, strerror (ENOENT));
return (EXECUTION_FAILURE);
}
#endif
}
else
dirname = list->word->word;
/* When we get here, DIRNAME is the directory to change to. If we
chdir successfully, just return. */
if (change_to_directory (dirname, no_symlinks))
{
if (lflag & LCD_PRINTPATH)
printf ("%s\n", dirname);
return (bindpwd (no_symlinks));
}
/* If the user requests it, then perhaps this is the name of
a shell variable, whose value contains the directory to
change to. */
if (lflag & LCD_DOVARS)
{
temp = get_string_value (dirname);
if (temp && change_to_directory (temp, no_symlinks))
{
printf ("%s\n", temp);
return (bindpwd (no_symlinks));
}
}
/* If the user requests it, try to find a directory name similar in
spelling to the one requested, in case the user made a simple
typo. This is similar to the UNIX 8th and 9th Edition shells. */
if (lflag & LCD_DOSPELL)
{
temp = dirspell (dirname);
if (temp && change_to_directory (temp, no_symlinks))
{
printf ("%s\n", temp);
return (bindpwd (no_symlinks));
}
else
FREE (temp);
}
builtin_error ("%s: %s", dirname, strerror (errno));
return (EXECUTION_FAILURE);
}
$BUILTIN pwd
$FUNCTION pwd_builtin
$SHORT_DOC pwd [-LP]
Print the name of the current working directory.
Options:
-L print the value of $PWD if it names the current working
directory
-P print the physical directory, without any symbolic links
By default, `pwd' behaves as if `-L' were specified.
Exit Status:
Returns 0 unless an invalid option is given or the current directory
cannot be read.
$END
/* Non-zero means that pwd always prints the physical directory, without
symbolic links. */
static int verbatim_pwd;
/* Print the name of the current working directory. */
int
pwd_builtin (list)
WORD_LIST *list;
{
char *directory;
int opt, pflag;
verbatim_pwd = no_symbolic_links;
pflag = 0;
reset_internal_getopt ();
while ((opt = internal_getopt (list, "LP")) != -1)
{
switch (opt)
{
case 'P':
verbatim_pwd = pflag = 1;
break;
case 'L':
verbatim_pwd = 0;
break;
default:
builtin_usage ();
return (EXECUTION_FAILURE);
}
}
list = loptend;
#define tcwd the_current_working_directory
directory = tcwd ? (verbatim_pwd ? sh_physpath (tcwd, 0) : tcwd)
: get_working_directory ("pwd");
/* Try again using getcwd() if canonicalization fails (for instance, if
the file system has changed state underneath bash). */
if ((tcwd && directory == 0) ||
(posixly_correct && same_file (".", tcwd, (struct stat *)0, (struct stat *)0) == 0))
directory = resetpwd ("pwd");
#undef tcwd
if (directory)
{
opt = EXECUTION_SUCCESS;
printf ("%s\n", directory);
/* This is dumb but posix-mandated. */
if (posixly_correct && pflag)
opt = setpwd (directory);
if (directory != the_current_working_directory)
free (directory);
return (sh_chkwrite (opt));
}
else
return (EXECUTION_FAILURE);
}
/* Do the work of changing to the directory NEWDIR. Handle symbolic
link following, etc. This function *must* return with
the_current_working_directory either set to NULL (in which case
getcwd() will eventually be called), or set to a string corresponding
to the working directory. Return 1 on success, 0 on failure. */
static int
change_to_directory (newdir, nolinks)
char *newdir;
int nolinks;
{
char *t, *tdir;
int err, canon_failed, r, ndlen, dlen;
tdir = (char *)NULL;
if (the_current_working_directory == 0)
{
t = get_working_directory ("chdir");
FREE (t);
}
t = make_absolute (newdir, the_current_working_directory);
/* TDIR is either the canonicalized absolute pathname of NEWDIR
(nolinks == 0) or the absolute physical pathname of NEWDIR
(nolinks != 0). */
tdir = nolinks ? sh_physpath (t, 0)
: sh_canonpath (t, PATH_CHECKDOTDOT|PATH_CHECKEXISTS);
ndlen = strlen (newdir);
dlen = strlen (t);
/* Use the canonicalized version of NEWDIR, or, if canonicalization
failed, use the non-canonical form. */
canon_failed = 0;
if (tdir && *tdir)
free (t);
else
{
FREE (tdir);
tdir = t;
canon_failed = 1;
}
/* In POSIX mode, if we're resolving symlinks logically and sh_canonpath
returns NULL (because it checks the path, it will return NULL if the
resolved path doesn't exist), fail immediately. */
if (posixly_correct && nolinks == 0 && canon_failed && (errno != ENAMETOOLONG || ndlen > PATH_MAX))
{
#if defined ENAMETOOLONG
if (errno != ENOENT && errno != ENAMETOOLONG)
#else
if (errno != ENOENT)
#endif
errno = ENOTDIR;
free (tdir);
return (0);
}
/* If the chdir succeeds, update the_current_working_directory. */
if (chdir (nolinks ? newdir : tdir) == 0)
{
/* If canonicalization failed, but the chdir succeeded, reset the
shell's idea of the_current_working_directory. */
if (canon_failed)
{
t = resetpwd ("cd");
if (t == 0)
set_working_directory (tdir);
}
else
set_working_directory (tdir);
free (tdir);
return (1);
}
/* We failed to change to the appropriate directory name. If we tried
what the user passed (nolinks != 0), punt now. */
if (nolinks)
{
free (tdir);
return (0);
}
err = errno;
/* We're not in physical mode (nolinks == 0), but we failed to change to
the canonicalized directory name (TDIR). Try what the user passed
verbatim. If we succeed, reinitialize the_current_working_directory. */
if (chdir (newdir) == 0)
{
t = resetpwd ("cd");
if (t == 0)
set_working_directory (tdir);
else
free (t);
r = 1;
}
else
{
errno = err;
r = 0;
}
free (tdir);
return r;
}
+15 -5
View File
@@ -685,6 +685,7 @@ printstr (fmt, string, len, fieldwidth, precision)
#endif
int padlen, nc, ljust, i;
int fw, pr; /* fieldwidth and precision */
intmax_t mfw, mpr;
#if 0
if (string == 0 || *string == '\0')
@@ -701,6 +702,8 @@ printstr (fmt, string, len, fieldwidth, precision)
ljust = fw = 0;
pr = -1;
mfw = 0;
mpr = -1;
/* skip flags */
while (strchr (SKIP1, *fmt))
@@ -710,7 +713,7 @@ printstr (fmt, string, len, fieldwidth, precision)
fmt++;
}
/* get fieldwidth, if present */
/* get fieldwidth, if present. rely on caller to clamp fieldwidth at INT_MAX */
if (*fmt == '*')
{
fmt++;
@@ -723,9 +726,11 @@ printstr (fmt, string, len, fieldwidth, precision)
}
else if (DIGIT (*fmt))
{
fw = *fmt++ - '0';
mfw = *fmt++ - '0';
while (DIGIT (*fmt))
fw = (fw * 10) + (*fmt++ - '0');
mfw = (mfw * 10) + (*fmt++ - '0');
/* Error if fieldwidth > INT_MAX here? */
fw = (mfw < 0 || mfw > INT_MAX) ? INT_MAX : mfw;
}
/* get precision, if present */
@@ -739,9 +744,11 @@ printstr (fmt, string, len, fieldwidth, precision)
}
else if (DIGIT (*fmt))
{
pr = *fmt++ - '0';
mpr = *fmt++ - '0';
while (DIGIT (*fmt))
pr = (pr * 10) + (*fmt++ - '0');
mpr = (mpr * 10) + (*fmt++ - '0');
/* Error if precision > INT_MAX here? */
pr = (mpr < 0 || mpr > INT_MAX) ? INT_MAX : mpr;
}
}
@@ -1093,6 +1100,9 @@ getint ()
ret = getintmax ();
if (garglist == 0)
return ret;
if (ret > INT_MAX)
{
printf_erange (garglist->word->word);
+1252
View File
File diff suppressed because it is too large Load Diff
+12 -6
View File
@@ -5,12 +5,12 @@
.\" Case Western Reserve University
.\" chet@po.cwru.edu
.\"
.\" Last Change: Thu Jul 7 07:26:51 EDT 2011
.\" Last Change: Thu Jul 28 18:11:21 EDT 2011
.\"
.\" bash_builtins, strip all but Built-Ins section
.if \n(zZ=1 .ig zZ
.if \n(zY=1 .ig zY
.TH BASH 1 "2011 July 7" "GNU Bash 4.2"
.TH BASH 1 "2011 July 28" "GNU Bash 4.2"
.\"
.\" There's some problem with having a `@'
.\" in a tagged paragraph with the BSD man macros.
@@ -1207,6 +1207,9 @@ Assignment statements may also appear as arguments to the
and
.B local
builtin commands.
When in \fIposix mode\fP, these builtins may appear in a command after
one or more instances of the \fBcommand\fP builtin and retain these
assignment statement properties.
.PP
In the context where an assignment statement is assigning a value
to a shell variable or array index, the += operator can be used to
@@ -3376,7 +3379,8 @@ Each redirection that may be preceded by a file descriptor number
may instead be preceded by a word of the form {\fIvarname\fP}.
In this case, for each redirection operator except
>&- and <&-, the shell will allocate a file descriptor greater
than 10 and assign it to \fIvarname\fP. If >&- or <&- is preceded
than or equal to 10 and assign it to \fIvarname\fP.
If >&- or <&- is preceded
by {\fIvarname\fP}, the value of \fIvarname\fP defines the file
descriptor to close.
.PP
@@ -6852,9 +6856,10 @@ after a successful directory change, \fBcd\fP will return an unsuccessful
status.
An argument of
.B \-
is equivalent to
is converted to
.SM
.BR $OLDPWD .
.B $OLDPWD
before the directory change is attempted.
If a non-empty directory name from
.SM
.B CDPATH
@@ -8259,7 +8264,8 @@ starting with zero) is at the top.
Adds
.I dir
to the directory stack at the top, making it the
new current working directory.
new current working directory as if it had been supplied as the argument
to the \fBcd\fP builtin.
.PD
.PP
If the
+9981
View File
File diff suppressed because it is too large Load Diff
+11 -1
View File
@@ -1381,6 +1381,9 @@ Assignment statements may also appear as arguments to the
@code{alias},
@code{declare}, @code{typeset}, @code{export}, @code{readonly},
and @code{local} builtin commands.
When in @sc{posix} mode (@pxref{Bash POSIX Mode}), these builtins may appear
in a command after one or more instances of the @code{command} builtin
and retain these assignment statement properties.
In the context where an assignment statement is assigning a value
to a shell variable or array index (@pxref{Arrays}), the @samp{+=}
@@ -2965,7 +2968,8 @@ If the @option{-e} option is supplied with @option{-P}
and the current working directory cannot be successfully determined
after a successful directory change, @code{cd} will return an unsuccessful
status.
If @var{directory} is @samp{-}, it is equivalent to @env{$OLDPWD}.
If @var{directory} is @samp{-}, it is converted to @env{$OLDPWD}
before the directory change is attempted.
If a non-empty directory name from @env{CDPATH} is used, or if
@samp{-} is the first argument, and the directory change is
@@ -6676,6 +6680,12 @@ the normal Bash files.
Tilde expansion is only performed on assignments preceding a command
name, rather than on all assignment statements on the line.
@item
The @code{command} builtin does not prevent builtins that take assignment
statements as arguments from expanding them as assignment statements;
when not in POSIX mode, assignment builtins lose their assignment
statement expansion properties when preceded by @code{command}.
@item
The default history file is @file{~/.sh_history} (this is the
default value of @env{$HISTFILE}).
+8216
View File
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -2,9 +2,9 @@
Copyright (C) 1988-2011 Free Software Foundation, Inc.
@end ignore
@set LASTCHANGE Thu Jul 7 07:34:57 EDT 2011
@set LASTCHANGE Thu Jul 28 18:11:38 EDT 2011
@set EDITION 4.2
@set VERSION 4.2
@set UPDATED 7 July 2011
@set UPDATED 28 July 2011
@set UPDATED-MONTH July 2011
+10
View File
@@ -0,0 +1,10 @@
@ignore
Copyright (C) 1988-2011 Free Software Foundation, Inc.
@end ignore
@set LASTCHANGE Sun Jul 24 16:17:58 EDT 2011
@set EDITION 4.2
@set VERSION 4.2
@set UPDATED 24 July 2011
@set UPDATED-MONTH July 2011
+16 -6
View File
@@ -3652,7 +3652,7 @@ static void
fix_assignment_words (words)
WORD_LIST *words;
{
WORD_LIST *w;
WORD_LIST *w, *wcmd;
struct builtin *b;
int assoc;
@@ -3662,16 +3662,24 @@ fix_assignment_words (words)
b = 0;
assoc = 0;
wcmd = words;
for (w = words; w; w = w->next)
if (w->word->flags & W_ASSIGNMENT)
{
if (b == 0)
{
b = builtin_address_internal (words->word->word, 0);
/* Posix (post-2008) says that `command' doesn't change whether
or not the builtin it shadows is a `declaration command', even
though it removes other special builtin properties. In Posix
mode, we skip over one or more instances of `command' and
deal with the next word as the assignment builtin. */
while (posixly_correct && wcmd && wcmd->word && wcmd->word->word && STREQ (wcmd->word->word, "command"))
wcmd = wcmd->next;
b = builtin_address_internal (wcmd->word->word, 0);
if (b == 0 || (b->flags & ASSIGNMENT_BUILTIN) == 0)
return;
else if (b && (b->flags & ASSIGNMENT_BUILTIN))
words->word->flags |= W_ASSNBLTIN;
wcmd->word->flags |= W_ASSNBLTIN;
}
w->word->flags |= (W_NOSPLIT|W_NOGLOB|W_TILDEEXP|W_ASSIGNARG);
#if defined (ARRAY_VARS)
@@ -3686,13 +3694,15 @@ fix_assignment_words (words)
{
if (b == 0)
{
b = builtin_address_internal (words->word->word, 0);
while (posixly_correct && wcmd && wcmd->word && wcmd->word->word && STREQ (wcmd->word->word, "command"))
wcmd = wcmd->next;
b = builtin_address_internal (wcmd->word->word, 0);
if (b == 0 || (b->flags & ASSIGNMENT_BUILTIN) == 0)
return;
else if (b && (b->flags & ASSIGNMENT_BUILTIN))
words->word->flags |= W_ASSNBLTIN;
wcmd->word->flags |= W_ASSNBLTIN;
}
if (words->word->flags & W_ASSNBLTIN)
if (wcmd->word->flags & W_ASSNBLTIN)
assoc = 1;
}
#endif
+5263
View File
File diff suppressed because it is too large Load Diff
+14 -5
View File
@@ -480,19 +480,23 @@ expassign ()
if (special)
{
if ((op == DIV || op == MOD) && value == 0)
{
if (noeval == 0)
evalerror (_("division by 0"));
else
value = 1;
}
switch (op)
{
case MUL:
lvalue *= value;
break;
case DIV:
if (value == 0)
evalerror (_("division by 0"));
lvalue /= value;
break;
case MOD:
if (value == 0)
evalerror (_("division by 0"));
lvalue %= value;
break;
case PLUS:
@@ -808,7 +812,12 @@ exp2 ()
val2 = exppower ();
if (((op == DIV) || (op == MOD)) && (val2 == 0))
evalerror (_("division by 0"));
{
if (noeval == 0)
evalerror (_("division by 0"));
else
val2 = 1;
}
if (op == MUL)
val1 *= val2;
+1473
View File
File diff suppressed because it is too large Load Diff
+9 -6
View File
@@ -62,8 +62,10 @@ _rl_callback_generic_arg *_rl_callback_data = 0;
whenever a complete line of input is ready. The user must then
call rl_callback_read_char() every time some input is available, and
rl_callback_read_char() will call the user's function with the complete
text read in at each end of line. The terminal is kept prepped and
signals handled all the time, except during calls to the user's function. */
text read in at each end of line. The terminal is kept prepped
all the time, except during calls to the user's function. Signal
handlers are only installed when the application calls back into
readline, so readline doesn't `steal' signals from the application. */
rl_vcpfunc_t *rl_linefunc; /* user callback function */
static int in_handler; /* terminal_prepped and signals set? */
@@ -80,10 +82,6 @@ _rl_callback_newline ()
if (rl_prep_term_function)
(*rl_prep_term_function) (_rl_meta_flag);
#if defined (HANDLE_SIGNALS)
rl_set_signals ();
#endif
}
readline_internal_setup ();
@@ -126,6 +124,11 @@ rl_callback_read_char ()
return;
}
#if defined (HANDLE_SIGNALS)
/* Install signal handlers only when readline has control. */
rl_set_signals ();
#endif
do
{
RL_CHECK_SIGNALS ();
+274
View File
@@ -0,0 +1,274 @@
/* callback.c -- functions to use readline as an X `callback' mechanism. */
/* Copyright (C) 1987-2009 Free Software Foundation, Inc.
This file is part of the GNU Readline Library (Readline), a library
for reading lines of text with interactive input and history editing.
Readline 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 3 of the License, or
(at your option) any later version.
Readline 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 Readline. If not, see <http://www.gnu.org/licenses/>.
*/
#define READLINE_LIBRARY
#if defined (HAVE_CONFIG_H)
# include <config.h>
#endif
#include "rlconf.h"
#if defined (READLINE_CALLBACKS)
#include <sys/types.h>
#ifdef HAVE_STDLIB_H
# include <stdlib.h>
#else
# include "ansi_stdlib.h"
#endif
#include <stdio.h>
/* System-specific feature definitions and include files. */
#include "rldefs.h"
#include "readline.h"
#include "rlprivate.h"
#include "xmalloc.h"
/* Private data for callback registration functions. See comments in
rl_callback_read_char for more details. */
_rl_callback_func_t *_rl_callback_func = 0;
_rl_callback_generic_arg *_rl_callback_data = 0;
/* **************************************************************** */
/* */
/* Callback Readline Functions */
/* */
/* **************************************************************** */
/* Allow using readline in situations where a program may have multiple
things to handle at once, and dispatches them via select(). Call
rl_callback_handler_install() with the prompt and a function to call
whenever a complete line of input is ready. The user must then
call rl_callback_read_char() every time some input is available, and
rl_callback_read_char() will call the user's function with the complete
text read in at each end of line. The terminal is kept prepped and
signals handled all the time, except during calls to the user's function. */
rl_vcpfunc_t *rl_linefunc; /* user callback function */
static int in_handler; /* terminal_prepped and signals set? */
/* Make sure the terminal is set up, initialize readline, and prompt. */
static void
_rl_callback_newline ()
{
rl_initialize ();
if (in_handler == 0)
{
in_handler = 1;
if (rl_prep_term_function)
(*rl_prep_term_function) (_rl_meta_flag);
}
readline_internal_setup ();
RL_CHECK_SIGNALS ();
}
/* Install a readline handler, set up the terminal, and issue the prompt. */
void
rl_callback_handler_install (prompt, linefunc)
const char *prompt;
rl_vcpfunc_t *linefunc;
{
rl_set_prompt (prompt);
RL_SETSTATE (RL_STATE_CALLBACK);
rl_linefunc = linefunc;
_rl_callback_newline ();
}
/* Read one character, and dispatch to the handler if it ends the line. */
void
rl_callback_read_char ()
{
char *line;
int eof, jcode;
static procenv_t olevel;
if (rl_linefunc == NULL)
{
_rl_errmsg ("readline_callback_read_char() called with no handler!");
abort ();
}
memcpy ((void *)olevel, (void *)_rl_top_level, sizeof (procenv_t));
jcode = setjmp (_rl_top_level);
if (jcode)
{
(*rl_redisplay_function) ();
_rl_want_redisplay = 0;
memcpy ((void *)_rl_top_level, (void *)olevel, sizeof (procenv_t));
return;
}
#if defined (HANDLE_SIGNALS)
/* Install signal handlers only when readline has control. */
rl_set_signals ();
#endif
do
{
RL_CHECK_SIGNALS ();
if (RL_ISSTATE (RL_STATE_ISEARCH))
{
eof = _rl_isearch_callback (_rl_iscxt);
if (eof == 0 && (RL_ISSTATE (RL_STATE_ISEARCH) == 0) && RL_ISSTATE (RL_STATE_INPUTPENDING))
rl_callback_read_char ();
return;
}
else if (RL_ISSTATE (RL_STATE_NSEARCH))
{
eof = _rl_nsearch_callback (_rl_nscxt);
return;
}
#if defined (VI_MODE)
else if (RL_ISSTATE (RL_STATE_VIMOTION))
{
eof = _rl_vi_domove_callback (_rl_vimvcxt);
/* Should handle everything, including cleanup, numeric arguments,
and turning off RL_STATE_VIMOTION */
if (RL_ISSTATE (RL_STATE_NUMERICARG) == 0)
_rl_internal_char_cleanup ();
return;
}
#endif
else if (RL_ISSTATE (RL_STATE_NUMERICARG))
{
eof = _rl_arg_callback (_rl_argcxt);
if (eof == 0 && (RL_ISSTATE (RL_STATE_NUMERICARG) == 0) && RL_ISSTATE (RL_STATE_INPUTPENDING))
rl_callback_read_char ();
/* XXX - this should handle _rl_last_command_was_kill better */
else if (RL_ISSTATE (RL_STATE_NUMERICARG) == 0)
_rl_internal_char_cleanup ();
return;
}
else if (RL_ISSTATE (RL_STATE_MULTIKEY))
{
eof = _rl_dispatch_callback (_rl_kscxt); /* For now */
while ((eof == -1 || eof == -2) && RL_ISSTATE (RL_STATE_MULTIKEY) && _rl_kscxt && (_rl_kscxt->flags & KSEQ_DISPATCHED))
eof = _rl_dispatch_callback (_rl_kscxt);
if (RL_ISSTATE (RL_STATE_MULTIKEY) == 0)
{
_rl_internal_char_cleanup ();
_rl_want_redisplay = 1;
}
}
else if (_rl_callback_func)
{
/* This allows functions that simply need to read an additional
character (like quoted-insert) to register a function to be
called when input is available. _rl_callback_data is simply a
pointer to a struct that has the argument count originally
passed to the registering function and space for any additional
parameters. */
eof = (*_rl_callback_func) (_rl_callback_data);
/* If the function `deregisters' itself, make sure the data is
cleaned up. */
if (_rl_callback_func == 0)
{
if (_rl_callback_data)
{
_rl_callback_data_dispose (_rl_callback_data);
_rl_callback_data = 0;
}
_rl_internal_char_cleanup ();
}
}
else
eof = readline_internal_char ();
RL_CHECK_SIGNALS ();
if (rl_done == 0 && _rl_want_redisplay)
{
(*rl_redisplay_function) ();
_rl_want_redisplay = 0;
}
if (rl_done)
{
line = readline_internal_teardown (eof);
if (rl_deprep_term_function)
(*rl_deprep_term_function) ();
#if defined (HANDLE_SIGNALS)
rl_clear_signals ();
#endif
in_handler = 0;
(*rl_linefunc) (line);
/* If the user did not clear out the line, do it for him. */
if (rl_line_buffer[0])
_rl_init_line_state ();
/* Redisplay the prompt if readline_handler_{install,remove}
not called. */
if (in_handler == 0 && rl_linefunc)
_rl_callback_newline ();
}
}
while (rl_pending_input || _rl_pushed_input_available () || RL_ISSTATE (RL_STATE_MACROINPUT));
}
/* Remove the handler, and make sure the terminal is in its normal state. */
void
rl_callback_handler_remove ()
{
rl_linefunc = NULL;
RL_UNSETSTATE (RL_STATE_CALLBACK);
RL_CHECK_SIGNALS ();
if (in_handler)
{
in_handler = 0;
if (rl_deprep_term_function)
(*rl_deprep_term_function) ();
#if defined (HANDLE_SIGNALS)
rl_clear_signals ();
#endif
}
}
_rl_callback_generic_arg *
_rl_callback_data_alloc (count)
int count;
{
_rl_callback_generic_arg *arg;
arg = (_rl_callback_generic_arg *)xmalloc (sizeof (_rl_callback_generic_arg));
arg->count = count;
arg->i1 = arg->i2 = 0;
return arg;
}
void _rl_callback_data_dispose (arg)
_rl_callback_generic_arg *arg;
{
xfree (arg);
}
#endif
+1 -1
View File
@@ -72,7 +72,7 @@
# define IN_CTYPE_DOMAIN(c) isascii(c)
#endif
#if !defined (isxdigit) && !defined (HAVE_ISXDIGIT)
#if !defined (isxdigit) && !defined (HAVE_ISXDIGIT) && !defined (__cplusplus)
# define isxdigit(c) (isdigit((c)) || ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F'))
#endif
+164
View File
@@ -0,0 +1,164 @@
/* chardefs.h -- Character definitions for readline. */
/* Copyright (C) 1994-2009 Free Software Foundation, Inc.
This file is part of the GNU Readline Library (Readline), a library
for reading lines of text with interactive input and history editing.
Readline 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 3 of the License, or
(at your option) any later version.
Readline 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 Readline. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _CHARDEFS_H_
#define _CHARDEFS_H_
#include <ctype.h>
#if defined (HAVE_CONFIG_H)
# if defined (HAVE_STRING_H)
# if ! defined (STDC_HEADERS) && defined (HAVE_MEMORY_H)
# include <memory.h>
# endif
# include <string.h>
# endif /* HAVE_STRING_H */
# if defined (HAVE_STRINGS_H)
# include <strings.h>
# endif /* HAVE_STRINGS_H */
#else
# include <string.h>
#endif /* !HAVE_CONFIG_H */
#ifndef whitespace
#define whitespace(c) (((c) == ' ') || ((c) == '\t'))
#endif
#ifdef CTRL
# undef CTRL
#endif
#ifdef UNCTRL
# undef UNCTRL
#endif
/* Some character stuff. */
#define control_character_threshold 0x020 /* Smaller than this is control. */
#define control_character_mask 0x1f /* 0x20 - 1 */
#define meta_character_threshold 0x07f /* Larger than this is Meta. */
#define control_character_bit 0x40 /* 0x000000, must be off. */
#define meta_character_bit 0x080 /* x0000000, must be on. */
#define largest_char 255 /* Largest character value. */
#define CTRL_CHAR(c) ((c) < control_character_threshold && (((c) & 0x80) == 0))
#define META_CHAR(c) ((c) > meta_character_threshold && (c) <= largest_char)
#define CTRL(c) ((c) & control_character_mask)
#define META(c) ((c) | meta_character_bit)
#define UNMETA(c) ((c) & (~meta_character_bit))
#define UNCTRL(c) _rl_to_upper(((c)|control_character_bit))
#if defined STDC_HEADERS || (!defined (isascii) && !defined (HAVE_ISASCII))
# define IN_CTYPE_DOMAIN(c) 1
#else
# define IN_CTYPE_DOMAIN(c) isascii(c)
#endif
#if !defined (isxdigit) && !defined (HAVE_ISXDIGIT)
# define isxdigit(c) (isdigit((c)) || ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F'))
#endif
#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
/* Beware: these only work with single-byte ASCII characters. */
#define ISALNUM(c) (IN_CTYPE_DOMAIN (c) && isalnum (c))
#define ISALPHA(c) (IN_CTYPE_DOMAIN (c) && isalpha (c))
#define ISDIGIT(c) (IN_CTYPE_DOMAIN (c) && isdigit (c))
#define ISLOWER(c) (IN_CTYPE_DOMAIN (c) && islower (c))
#define ISPRINT(c) (IN_CTYPE_DOMAIN (c) && isprint (c))
#define ISUPPER(c) (IN_CTYPE_DOMAIN (c) && isupper (c))
#define ISXDIGIT(c) (IN_CTYPE_DOMAIN (c) && isxdigit (c))
#define _rl_lowercase_p(c) (NON_NEGATIVE(c) && ISLOWER(c))
#define _rl_uppercase_p(c) (NON_NEGATIVE(c) && ISUPPER(c))
#define _rl_digit_p(c) ((c) >= '0' && (c) <= '9')
#define _rl_pure_alphabetic(c) (NON_NEGATIVE(c) && ISALPHA(c))
#define ALPHABETIC(c) (NON_NEGATIVE(c) && ISALNUM(c))
#ifndef _rl_to_upper
# define _rl_to_upper(c) (_rl_lowercase_p(c) ? toupper((unsigned char)c) : (c))
# define _rl_to_lower(c) (_rl_uppercase_p(c) ? tolower((unsigned char)c) : (c))
#endif
#ifndef _rl_digit_value
# define _rl_digit_value(x) ((x) - '0')
#endif
#ifndef _rl_isident
# define _rl_isident(c) (ISALNUM(c) || (c) == '_')
#endif
#ifndef ISOCTAL
# define ISOCTAL(c) ((c) >= '0' && (c) <= '7')
#endif
#define OCTVALUE(c) ((c) - '0')
#define HEXVALUE(c) \
(((c) >= 'a' && (c) <= 'f') \
? (c)-'a'+10 \
: (c) >= 'A' && (c) <= 'F' ? (c)-'A'+10 : (c)-'0')
#ifndef NEWLINE
#define NEWLINE '\n'
#endif
#ifndef RETURN
#define RETURN CTRL('M')
#endif
#ifndef RUBOUT
#define RUBOUT 0x7f
#endif
#ifndef TAB
#define TAB '\t'
#endif
#ifdef ABORT_CHAR
#undef ABORT_CHAR
#endif
#define ABORT_CHAR CTRL('G')
#ifdef PAGE
#undef PAGE
#endif
#define PAGE CTRL('L')
#ifdef SPACE
#undef SPACE
#endif
#define SPACE ' ' /* XXX - was 0x20 */
#ifdef ESC
#undef ESC
#endif
#define ESC CTRL('[')
#endif /* _CHARDEFS_H_ */
+40 -10
View File
@@ -312,6 +312,8 @@ _rl_search_getchar (cxt)
RL_UNSETSTATE(RL_STATE_MOREINPUT);
#if defined (HANDLE_MULTIBYTE)
/* This ends up with C (and LASTC) being set to the last byte of the
multibyte character. In most cases c == lastc == mb[0] */
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
c = cxt->lastc = _rl_read_mbstring (cxt->lastc, cxt->mb, MB_LEN_MAX);
#endif
@@ -354,6 +356,18 @@ _rl_isearch_dispatch (cxt, c)
interpret here. Right now we just save the most recent character
that caused the index into a new keymap. */
cxt->prevc = c;
#if defined (HANDLE_MULTIBYTE)
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
{
if (cxt->mb[1] == 0)
{
cxt->pmb[0] = c; /* XXX should be == cxt->mb[0] */
cxt->pmb[1] = '\0';
}
else
memcpy (cxt->pmb, cxt->mb, sizeof (cxt->pmb));
}
#endif
return 1;
}
@@ -392,24 +406,36 @@ _rl_isearch_dispatch (cxt, c)
{
rl_stuff_char (cxt->lastc);
rl_execute_next (cxt->prevc);
/* XXX - do we insert everything in cxt->pmb? */
return (0);
}
/* Otherwise, if the current character is mapped to self-insert (i.e.,
not an editing command), and the previous character was a keymap
index, then we need to insert both the previous character and the
current character into the search string. */
/* Otherwise, if the current character is mapped to self-insert or
nothing (i.e., not an editing command), and the previous character
was a keymap index, then we need to insert both the previous
character and the current character into the search string. */
else if (cxt->lastc > 0 && cxt->prevc > 0 &&
cxt->keymap[cxt->prevc].type == ISKMAP &&
cxt->okeymap[cxt->lastc].type == ISFUNC && cxt->okeymap[cxt->lastc].function == rl_insert)
cxt->okeymap[cxt->lastc].type == ISFUNC &&
(cxt->okeymap[cxt->lastc].function == rl_insert || cxt->okeymap[cxt->lastc].function == 0))
{
/* Make lastc be the next character read */
/* XXX - do we insert everything in cxt->mb? */
rl_execute_next (cxt->lastc);
/* Dispatch on the previous character (insert into search string) */
cxt->lastc = cxt->prevc;
#if defined (HANDLE_MULTIBYTE)
/* Have to overwrite cxt->mb here because dispatch uses it below */
cxt->mb[0] = cxt->lastc;
cxt->mb[1] = '\0';
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
{
if (cxt->pmb[1] == 0)
{
cxt->mb[0] = cxt->lastc; /* == cxt->prevc */
cxt->mb[1] = '\0';
}
else
memcpy (cxt->mb, cxt->pmb, sizeof (cxt->mb));
}
#endif
cxt->prevc = 0;
}
}
@@ -577,8 +603,12 @@ _rl_isearch_dispatch (cxt, c)
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
{
int j, l;
for (j = 0, l = strlen (cxt->mb); j < l; )
cxt->search_string[cxt->search_string_index++] = cxt->mb[j++];
if (cxt->mb[0] == 0 || cxt->mb[1] == 0)
cxt->search_string[cxt->search_string_index++] = cxt->mb[0];
else
for (j = 0, l = RL_STRLEN (cxt->mb); j < l; )
cxt->search_string[cxt->search_string_index++] = cxt->mb[j++];
}
else
#endif
+758
View File
@@ -0,0 +1,758 @@
/* isearch.c - incremental searching */
/* **************************************************************** */
/* */
/* I-Search and Searching */
/* */
/* **************************************************************** */
/* Copyright (C) 1987-2011 Free Software Foundation, Inc.
This file is part of the GNU Readline Library (Readline), a library
for reading lines of text with interactive input and history editing.
Readline 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 3 of the License, or
(at your option) any later version.
Readline 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 Readline. If not, see <http://www.gnu.org/licenses/>.
*/
#define READLINE_LIBRARY
#if defined (HAVE_CONFIG_H)
# include <config.h>
#endif
#include <sys/types.h>
#include <stdio.h>
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#if defined (HAVE_STDLIB_H)
# include <stdlib.h>
#else
# include "ansi_stdlib.h"
#endif
#include "rldefs.h"
#include "rlmbutil.h"
#include "readline.h"
#include "history.h"
#include "rlprivate.h"
#include "xmalloc.h"
/* Variables exported to other files in the readline library. */
char *_rl_isearch_terminators = (char *)NULL;
_rl_search_cxt *_rl_iscxt = 0;
/* Variables imported from other files in the readline library. */
extern HIST_ENTRY *_rl_saved_line_for_history;
static int rl_search_history PARAMS((int, int));
static _rl_search_cxt *_rl_isearch_init PARAMS((int));
static void _rl_isearch_fini PARAMS((_rl_search_cxt *));
static int _rl_isearch_cleanup PARAMS((_rl_search_cxt *, int));
/* Last line found by the current incremental search, so we don't `find'
identical lines many times in a row. Now part of isearch context. */
/* static char *prev_line_found; */
/* Last search string and its length. */
static char *last_isearch_string;
static int last_isearch_string_len;
static char * const default_isearch_terminators = "\033\012";
_rl_search_cxt *
_rl_scxt_alloc (type, flags)
int type, flags;
{
_rl_search_cxt *cxt;
cxt = (_rl_search_cxt *)xmalloc (sizeof (_rl_search_cxt));
cxt->type = type;
cxt->sflags = flags;
cxt->search_string = 0;
cxt->search_string_size = cxt->search_string_index = 0;
cxt->lines = 0;
cxt->allocated_line = 0;
cxt->hlen = cxt->hindex = 0;
cxt->save_point = rl_point;
cxt->save_mark = rl_mark;
cxt->save_line = where_history ();
cxt->last_found_line = cxt->save_line;
cxt->prev_line_found = 0;
cxt->save_undo_list = 0;
cxt->keymap = _rl_keymap;
cxt->okeymap = _rl_keymap;
cxt->history_pos = 0;
cxt->direction = 0;
cxt->prevc = cxt->lastc = 0;
cxt->sline = 0;
cxt->sline_len = cxt->sline_index = 0;
cxt->search_terminators = 0;
return cxt;
}
void
_rl_scxt_dispose (cxt, flags)
_rl_search_cxt *cxt;
int flags;
{
FREE (cxt->search_string);
FREE (cxt->allocated_line);
FREE (cxt->lines);
xfree (cxt);
}
/* Search backwards through the history looking for a string which is typed
interactively. Start with the current line. */
int
rl_reverse_search_history (sign, key)
int sign, key;
{
return (rl_search_history (-sign, key));
}
/* Search forwards through the history looking for a string which is typed
interactively. Start with the current line. */
int
rl_forward_search_history (sign, key)
int sign, key;
{
return (rl_search_history (sign, key));
}
/* Display the current state of the search in the echo-area.
SEARCH_STRING contains the string that is being searched for,
DIRECTION is zero for forward, or non-zero for reverse,
WHERE is the history list number of the current line. If it is
-1, then this line is the starting one. */
static void
rl_display_search (search_string, reverse_p, where)
char *search_string;
int reverse_p, where;
{
char *message;
int msglen, searchlen;
searchlen = (search_string && *search_string) ? strlen (search_string) : 0;
message = (char *)xmalloc (searchlen + 33);
msglen = 0;
#if defined (NOTDEF)
if (where != -1)
{
sprintf (message, "[%d]", where + history_base);
msglen = strlen (message);
}
#endif /* NOTDEF */
message[msglen++] = '(';
if (reverse_p)
{
strcpy (message + msglen, "reverse-");
msglen += 8;
}
strcpy (message + msglen, "i-search)`");
msglen += 10;
if (search_string)
{
strcpy (message + msglen, search_string);
msglen += searchlen;
}
strcpy (message + msglen, "': ");
rl_message ("%s", message);
xfree (message);
(*rl_redisplay_function) ();
}
static _rl_search_cxt *
_rl_isearch_init (direction)
int direction;
{
_rl_search_cxt *cxt;
register int i;
HIST_ENTRY **hlist;
cxt = _rl_scxt_alloc (RL_SEARCH_ISEARCH, 0);
if (direction < 0)
cxt->sflags |= SF_REVERSE;
cxt->search_terminators = _rl_isearch_terminators ? _rl_isearch_terminators
: default_isearch_terminators;
/* Create an arrary of pointers to the lines that we want to search. */
hlist = history_list ();
rl_maybe_replace_line ();
i = 0;
if (hlist)
for (i = 0; hlist[i]; i++);
/* Allocate space for this many lines, +1 for the current input line,
and remember those lines. */
cxt->lines = (char **)xmalloc ((1 + (cxt->hlen = i)) * sizeof (char *));
for (i = 0; i < cxt->hlen; i++)
cxt->lines[i] = hlist[i]->line;
if (_rl_saved_line_for_history)
cxt->lines[i] = _rl_saved_line_for_history->line;
else
{
/* Keep track of this so we can free it. */
cxt->allocated_line = (char *)xmalloc (1 + strlen (rl_line_buffer));
strcpy (cxt->allocated_line, &rl_line_buffer[0]);
cxt->lines[i] = cxt->allocated_line;
}
cxt->hlen++;
/* The line where we start the search. */
cxt->history_pos = cxt->save_line;
rl_save_prompt ();
/* Initialize search parameters. */
cxt->search_string = (char *)xmalloc (cxt->search_string_size = 128);
cxt->search_string[cxt->search_string_index = 0] = '\0';
/* Normalize DIRECTION into 1 or -1. */
cxt->direction = (direction >= 0) ? 1 : -1;
cxt->sline = rl_line_buffer;
cxt->sline_len = strlen (cxt->sline);
cxt->sline_index = rl_point;
_rl_iscxt = cxt; /* save globally */
return cxt;
}
static void
_rl_isearch_fini (cxt)
_rl_search_cxt *cxt;
{
/* First put back the original state. */
strcpy (rl_line_buffer, cxt->lines[cxt->save_line]);
rl_restore_prompt ();
/* Save the search string for possible later use. */
FREE (last_isearch_string);
last_isearch_string = cxt->search_string;
last_isearch_string_len = cxt->search_string_index;
cxt->search_string = 0;
if (cxt->last_found_line < cxt->save_line)
rl_get_previous_history (cxt->save_line - cxt->last_found_line, 0);
else
rl_get_next_history (cxt->last_found_line - cxt->save_line, 0);
/* If the string was not found, put point at the end of the last matching
line. If last_found_line == orig_line, we didn't find any matching
history lines at all, so put point back in its original position. */
if (cxt->sline_index < 0)
{
if (cxt->last_found_line == cxt->save_line)
cxt->sline_index = cxt->save_point;
else
cxt->sline_index = strlen (rl_line_buffer);
rl_mark = cxt->save_mark;
}
rl_point = cxt->sline_index;
/* Don't worry about where to put the mark here; rl_get_previous_history
and rl_get_next_history take care of it. */
rl_clear_message ();
}
int
_rl_search_getchar (cxt)
_rl_search_cxt *cxt;
{
int c;
/* Read a key and decide how to proceed. */
RL_SETSTATE(RL_STATE_MOREINPUT);
c = cxt->lastc = rl_read_key ();
RL_UNSETSTATE(RL_STATE_MOREINPUT);
#if defined (HANDLE_MULTIBYTE)
/* This ends up with C (and LASTC) being set to the last byte of the
multibyte character. In most cases c == lastc == mb[0] */
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
c = cxt->lastc = _rl_read_mbstring (cxt->lastc, cxt->mb, MB_LEN_MAX);
#endif
return c;
}
#define ENDSRCH_CHAR(c) \
((CTRL_CHAR (c) || META_CHAR (c) || (c) == RUBOUT) && ((c) != CTRL ('G')))
/* Process just-read character C according to isearch context CXT. Return
-1 if the caller should just free the context and return, 0 if we should
break out of the loop, and 1 if we should continue to read characters. */
int
_rl_isearch_dispatch (cxt, c)
_rl_search_cxt *cxt;
int c;
{
int n, wstart, wlen, limit, cval;
rl_command_func_t *f;
f = (rl_command_func_t *)NULL;
if (c < 0)
{
cxt->sflags |= SF_FAILED;
cxt->history_pos = cxt->last_found_line;
return -1;
}
/* If we are moving into a new keymap, modify cxt->keymap and go on.
This can be a problem if c == ESC and we want to terminate the
incremental search, so we check */
if (c >= 0 && cxt->keymap[c].type == ISKMAP && strchr (cxt->search_terminators, cxt->lastc) == 0)
{
cxt->keymap = FUNCTION_TO_KEYMAP (cxt->keymap, c);
cxt->sflags |= SF_CHGKMAP;
/* XXX - we should probably save this sequence, so we can do
something useful if this doesn't end up mapping to a command we
interpret here. Right now we just save the most recent character
that caused the index into a new keymap. */
cxt->prevc = c;
#if defined (HANDLE_MULTIBYTE)
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
{
if (cxt->mb[1] == 0)
{
cxt->pmb[0] = c; /* XXX should be == cxt->mb[0] */
cxt->pmb[1] = '\0';
}
else
memcpy (cxt->pmb, cxt->mb, sizeof (cxt->pmb));
}
#endif
return 1;
}
/* Translate the keys we do something with to opcodes. */
if (c >= 0 && cxt->keymap[c].type == ISFUNC)
{
f = cxt->keymap[c].function;
if (f == rl_reverse_search_history)
cxt->lastc = (cxt->sflags & SF_REVERSE) ? -1 : -2;
else if (f == rl_forward_search_history)
cxt->lastc = (cxt->sflags & SF_REVERSE) ? -2 : -1;
else if (f == rl_rubout)
cxt->lastc = -3;
else if (c == CTRL ('G') || f == rl_abort)
cxt->lastc = -4;
else if (c == CTRL ('W') || f == rl_unix_word_rubout) /* XXX */
cxt->lastc = -5;
else if (c == CTRL ('Y') || f == rl_yank) /* XXX */
cxt->lastc = -6;
}
/* If we changed the keymap earlier while translating a key sequence into
a command, restore it now that we've succeeded. */
if (cxt->sflags & SF_CHGKMAP)
{
cxt->keymap = cxt->okeymap;
cxt->sflags &= ~SF_CHGKMAP;
/* If we indexed into a new keymap, but didn't map to a command that
affects the search (lastc > 0), and the character that mapped to a
new keymap would have ended the search (ENDSRCH_CHAR(cxt->prevc)),
handle that now as if the previous char would have ended the search
and we would have read the current character. */
/* XXX - should we check cxt->mb? */
if (cxt->lastc > 0 && ENDSRCH_CHAR (cxt->prevc))
{
rl_stuff_char (cxt->lastc);
rl_execute_next (cxt->prevc);
return (0);
}
/* Otherwise, if the current character is mapped to self-insert or
nothing (i.e., not an editing command), and the previous character
was a keymap index, then we need to insert both the previous
character and the current character into the search string. */
else if (cxt->lastc > 0 && cxt->prevc > 0 &&
cxt->keymap[cxt->prevc].type == ISKMAP &&
cxt->okeymap[cxt->lastc].type == ISFUNC &&
(cxt->okeymap[cxt->lastc].function == rl_insert || cxt->okeymap[cxt->lastc].function == 0))
{
/* Make lastc be the next character read */
rl_execute_next (cxt->lastc);
/* Dispatch on the previous character (insert into search string) */
cxt->lastc = cxt->prevc;
#if defined (HANDLE_MULTIBYTE)
/* Have to overwrite cxt->mb here because dispatch uses it below */
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
{
if (cxt->pmb[1] == 0)
{
cxt->mb[0] = cxt->lastc; /* == cxt->prevc */
cxt->mb[1] = '\0';
}
else
memcpy (cxt->mb, cxt->pmb, sizeof (cxt->mb));
}
#endif
cxt->prevc = 0;
}
}
/* The characters in isearch_terminators (set from the user-settable
variable isearch-terminators) are used to terminate the search but
not subsequently execute the character as a command. The default
value is "\033\012" (ESC and C-J). */
if (cxt->lastc > 0 && strchr (cxt->search_terminators, cxt->lastc))
{
/* ESC still terminates the search, but if there is pending
input or if input arrives within 0.1 seconds (on systems
with select(2)) it is used as a prefix character
with rl_execute_next. WATCH OUT FOR THIS! This is intended
to allow the arrow keys to be used like ^F and ^B are used
to terminate the search and execute the movement command.
XXX - since _rl_input_available depends on the application-
settable keyboard timeout value, this could alternatively
use _rl_input_queued(100000) */
if (cxt->lastc == ESC && _rl_input_available ())
rl_execute_next (ESC);
return (0);
}
#if defined (HANDLE_MULTIBYTE)
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
{
if (cxt->lastc >= 0 && (cxt->mb[0] && cxt->mb[1] == '\0') && ENDSRCH_CHAR (cxt->lastc))
{
/* This sets rl_pending_input to LASTC; it will be picked up the next
time rl_read_key is called. */
rl_execute_next (cxt->lastc);
return (0);
}
}
else
#endif
if (cxt->lastc >= 0 && ENDSRCH_CHAR (cxt->lastc))
{
/* This sets rl_pending_input to LASTC; it will be picked up the next
time rl_read_key is called. */
rl_execute_next (cxt->lastc);
return (0);
}
/* Now dispatch on the character. `Opcodes' affect the search string or
state. Other characters are added to the string. */
switch (cxt->lastc)
{
/* search again */
case -1:
if (cxt->search_string_index == 0)
{
if (last_isearch_string)
{
cxt->search_string_size = 64 + last_isearch_string_len;
cxt->search_string = (char *)xrealloc (cxt->search_string, cxt->search_string_size);
strcpy (cxt->search_string, last_isearch_string);
cxt->search_string_index = last_isearch_string_len;
rl_display_search (cxt->search_string, (cxt->sflags & SF_REVERSE), -1);
break;
}
return (1);
}
else if (cxt->sflags & SF_REVERSE)
cxt->sline_index--;
else if (cxt->sline_index != cxt->sline_len)
cxt->sline_index++;
else
rl_ding ();
break;
/* switch directions */
case -2:
cxt->direction = -cxt->direction;
if (cxt->direction < 0)
cxt->sflags |= SF_REVERSE;
else
cxt->sflags &= ~SF_REVERSE;
break;
/* delete character from search string. */
case -3: /* C-H, DEL */
/* This is tricky. To do this right, we need to keep a
stack of search positions for the current search, with
sentinels marking the beginning and end. But this will
do until we have a real isearch-undo. */
if (cxt->search_string_index == 0)
rl_ding ();
else
cxt->search_string[--cxt->search_string_index] = '\0';
break;
case -4: /* C-G, abort */
rl_replace_line (cxt->lines[cxt->save_line], 0);
rl_point = cxt->save_point;
rl_mark = cxt->save_mark;
rl_restore_prompt();
rl_clear_message ();
return -1;
case -5: /* C-W */
/* skip over portion of line we already matched and yank word */
wstart = rl_point + cxt->search_string_index;
if (wstart >= rl_end)
{
rl_ding ();
break;
}
/* if not in a word, move to one. */
cval = _rl_char_value (rl_line_buffer, wstart);
if (_rl_walphabetic (cval) == 0)
{
rl_ding ();
break;
}
n = MB_NEXTCHAR (rl_line_buffer, wstart, 1, MB_FIND_NONZERO);;
while (n < rl_end)
{
cval = _rl_char_value (rl_line_buffer, n);
if (_rl_walphabetic (cval) == 0)
break;
n = MB_NEXTCHAR (rl_line_buffer, n, 1, MB_FIND_NONZERO);;
}
wlen = n - wstart + 1;
if (cxt->search_string_index + wlen + 1 >= cxt->search_string_size)
{
cxt->search_string_size += wlen + 1;
cxt->search_string = (char *)xrealloc (cxt->search_string, cxt->search_string_size);
}
for (; wstart < n; wstart++)
cxt->search_string[cxt->search_string_index++] = rl_line_buffer[wstart];
cxt->search_string[cxt->search_string_index] = '\0';
break;
case -6: /* C-Y */
/* skip over portion of line we already matched and yank rest */
wstart = rl_point + cxt->search_string_index;
if (wstart >= rl_end)
{
rl_ding ();
break;
}
n = rl_end - wstart + 1;
if (cxt->search_string_index + n + 1 >= cxt->search_string_size)
{
cxt->search_string_size += n + 1;
cxt->search_string = (char *)xrealloc (cxt->search_string, cxt->search_string_size);
}
for (n = wstart; n < rl_end; n++)
cxt->search_string[cxt->search_string_index++] = rl_line_buffer[n];
cxt->search_string[cxt->search_string_index] = '\0';
break;
/* Add character to search string and continue search. */
default:
if (cxt->search_string_index + 2 >= cxt->search_string_size)
{
cxt->search_string_size += 128;
cxt->search_string = (char *)xrealloc (cxt->search_string, cxt->search_string_size);
}
#if defined (HANDLE_MULTIBYTE)
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
{
int j, l;
if (cxt->mb[0] == 0 || cxt->mb[1] == 0)
cxt->search_string[cxt->search_string_index++] = cxt->mb[0];
else
for (j = 0, l = RL_STRLEN (cxt->mb); j < l; )
cxt->search_string[cxt->search_string_index++] = cxt->mb[j++];
}
else
#endif
cxt->search_string[cxt->search_string_index++] = cxt->lastc; /* XXX - was c instead of lastc */
cxt->search_string[cxt->search_string_index] = '\0';
break;
}
for (cxt->sflags &= ~(SF_FOUND|SF_FAILED);; )
{
limit = cxt->sline_len - cxt->search_string_index + 1;
/* Search the current line. */
while ((cxt->sflags & SF_REVERSE) ? (cxt->sline_index >= 0) : (cxt->sline_index < limit))
{
if (STREQN (cxt->search_string, cxt->sline + cxt->sline_index, cxt->search_string_index))
{
cxt->sflags |= SF_FOUND;
break;
}
else
cxt->sline_index += cxt->direction;
}
if (cxt->sflags & SF_FOUND)
break;
/* Move to the next line, but skip new copies of the line
we just found and lines shorter than the string we're
searching for. */
do
{
/* Move to the next line. */
cxt->history_pos += cxt->direction;
/* At limit for direction? */
if ((cxt->sflags & SF_REVERSE) ? (cxt->history_pos < 0) : (cxt->history_pos == cxt->hlen))
{
cxt->sflags |= SF_FAILED;
break;
}
/* We will need these later. */
cxt->sline = cxt->lines[cxt->history_pos];
cxt->sline_len = strlen (cxt->sline);
}
while ((cxt->prev_line_found && STREQ (cxt->prev_line_found, cxt->lines[cxt->history_pos])) ||
(cxt->search_string_index > cxt->sline_len));
if (cxt->sflags & SF_FAILED)
break;
/* Now set up the line for searching... */
cxt->sline_index = (cxt->sflags & SF_REVERSE) ? cxt->sline_len - cxt->search_string_index : 0;
}
if (cxt->sflags & SF_FAILED)
{
/* We cannot find the search string. Ding the bell. */
rl_ding ();
cxt->history_pos = cxt->last_found_line;
return 1;
}
/* We have found the search string. Just display it. But don't
actually move there in the history list until the user accepts
the location. */
if (cxt->sflags & SF_FOUND)
{
cxt->prev_line_found = cxt->lines[cxt->history_pos];
rl_replace_line (cxt->lines[cxt->history_pos], 0);
rl_point = cxt->sline_index;
cxt->last_found_line = cxt->history_pos;
rl_display_search (cxt->search_string, (cxt->sflags & SF_REVERSE), (cxt->history_pos == cxt->save_line) ? -1 : cxt->history_pos);
}
return 1;
}
static int
_rl_isearch_cleanup (cxt, r)
_rl_search_cxt *cxt;
int r;
{
if (r >= 0)
_rl_isearch_fini (cxt);
_rl_scxt_dispose (cxt, 0);
_rl_iscxt = 0;
RL_UNSETSTATE(RL_STATE_ISEARCH);
return (r != 0);
}
/* Search through the history looking for an interactively typed string.
This is analogous to i-search. We start the search in the current line.
DIRECTION is which direction to search; >= 0 means forward, < 0 means
backwards. */
static int
rl_search_history (direction, invoking_key)
int direction, invoking_key;
{
_rl_search_cxt *cxt; /* local for now, but saved globally */
int c, r;
RL_SETSTATE(RL_STATE_ISEARCH);
cxt = _rl_isearch_init (direction);
rl_display_search (cxt->search_string, (cxt->sflags & SF_REVERSE), -1);
/* If we are using the callback interface, all we do is set up here and
return. The key is that we leave RL_STATE_ISEARCH set. */
if (RL_ISSTATE (RL_STATE_CALLBACK))
return (0);
r = -1;
for (;;)
{
c = _rl_search_getchar (cxt);
/* We might want to handle EOF here (c == 0) */
r = _rl_isearch_dispatch (cxt, cxt->lastc);
if (r <= 0)
break;
}
/* The searching is over. The user may have found the string that she
was looking for, or else she may have exited a failing search. If
LINE_INDEX is -1, then that shows that the string searched for was
not found. We use this to determine where to place rl_point. */
return (_rl_isearch_cleanup (cxt, r));
}
#if defined (READLINE_CALLBACKS)
/* Called from the callback functions when we are ready to read a key. The
callback functions know to call this because RL_ISSTATE(RL_STATE_ISEARCH).
If _rl_isearch_dispatch finishes searching, this function is responsible
for turning off RL_STATE_ISEARCH, which it does using _rl_isearch_cleanup. */
int
_rl_isearch_callback (cxt)
_rl_search_cxt *cxt;
{
int c, r;
c = _rl_search_getchar (cxt);
/* We might want to handle EOF here */
r = _rl_isearch_dispatch (cxt, cxt->lastc);
return (r <= 0) ? _rl_isearch_cleanup (cxt, r) : 0;
}
#endif
+5 -1
View File
@@ -2,7 +2,7 @@
for readline. This should be included after any files that define
system-specific constants like _POSIX_VERSION or USG. */
/* Copyright (C) 1987-2009 Free Software Foundation, Inc.
/* Copyright (C) 1987-2011 Free Software Foundation, Inc.
This file is part of the GNU Readline Library (Readline), a library
for reading lines of text with interactive input and history editing.
@@ -148,6 +148,10 @@ extern char *_rl_strpbrk PARAMS((const char *, const char *));
: ((a)[0] == (b)[0]) && (strncmp ((a), (b), (n)) == 0))
#endif
#if !defined (RL_STRLEN)
# define RL_STRLEN(s) (((s) && (s)[0]) ? ((s)[1] ? ((s)[2] ? strlen(s) : 2) : 1) : 0)
#endif
#if !defined (FREE)
# define FREE(x) if (x) free (x)
#endif
+1
View File
@@ -90,6 +90,7 @@ typedef struct __rl_search_context
int lastc;
#if defined (HANDLE_MULTIBYTE)
char mb[MB_LEN_MAX];
char pmb[MB_LEN_MAX];
#endif
char *sline;
-8
View File
@@ -146,15 +146,7 @@ static RETSIGTYPE
rl_signal_handler (sig)
int sig;
{
#if 0
#if defined (SIGWINCH)
if (_rl_interrupt_immediately || (sig != SIGWINCH && RL_ISSTATE(RL_STATE_CALLBACK)))
#else
if (_rl_interrupt_immediately || RL_ISSTATE(RL_STATE_CALLBACK))
#endif
#else
if (_rl_interrupt_immediately)
#endif
{
_rl_interrupt_immediately = 0;
_rl_handle_signal (sig);
+8
View File
@@ -146,7 +146,15 @@ static RETSIGTYPE
rl_signal_handler (sig)
int sig;
{
#if 0
#if defined (SIGWINCH)
if (_rl_interrupt_immediately || (sig != SIGWINCH && RL_ISSTATE(RL_STATE_CALLBACK)))
#else
if (_rl_interrupt_immediately || RL_ISSTATE(RL_STATE_CALLBACK))
#endif
#else
if (_rl_interrupt_immediately)
#endif
{
_rl_interrupt_immediately = 0;
_rl_handle_signal (sig);
+2 -3
View File
@@ -160,14 +160,13 @@ void
zsyncfd (fd)
int fd;
{
off_t off;
int r;
off_t off, r;
off = lused - lind;
r = 0;
if (off > 0)
r = lseek (fd, -off, SEEK_CUR);
if (r >= 0)
if (r != -1)
lused = lind = 0;
}
+172
View File
@@ -0,0 +1,172 @@
/* zread - read data from file descriptor into buffer with retries */
/* Copyright (C) 1999-2002 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 3 of the License, 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. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <sys/types.h>
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include <errno.h>
#if !defined (errno)
extern int errno;
#endif
#ifndef SEEK_CUR
# define SEEK_CUR 1
#endif
/* Read LEN bytes from FD into BUF. Retry the read on EINTR. Any other
error causes the loop to break. */
ssize_t
zread (fd, buf, len)
int fd;
char *buf;
size_t len;
{
ssize_t r;
while ((r = read (fd, buf, len)) < 0 && errno == EINTR)
;
return r;
}
/* Read LEN bytes from FD into BUF. Retry the read on EINTR, up to three
interrupts. Any other error causes the loop to break. */
#ifdef NUM_INTR
# undef NUM_INTR
#endif
#define NUM_INTR 3
ssize_t
zreadretry (fd, buf, len)
int fd;
char *buf;
size_t len;
{
ssize_t r;
int nintr;
for (nintr = 0; ; )
{
r = read (fd, buf, len);
if (r >= 0)
return r;
if (r == -1 && errno == EINTR)
{
if (++nintr >= NUM_INTR)
return -1;
continue;
}
return r;
}
}
/* Call read(2) and allow it to be interrupted. Just a stub for now. */
ssize_t
zreadintr (fd, buf, len)
int fd;
char *buf;
size_t len;
{
return (read (fd, buf, len));
}
/* Read one character from FD and return it in CP. Return values are as
in read(2). This does some local buffering to avoid many one-character
calls to read(2), like those the `read' builtin performs. */
static char lbuf[128];
static size_t lind, lused;
ssize_t
zreadc (fd, cp)
int fd;
char *cp;
{
ssize_t nr;
if (lind == lused || lused == 0)
{
nr = zread (fd, lbuf, sizeof (lbuf));
lind = 0;
if (nr <= 0)
{
lused = 0;
return nr;
}
lused = nr;
}
if (cp)
*cp = lbuf[lind++];
return 1;
}
/* Don't mix calls to zreadc and zreadcintr in the same function, since they
use the same local buffer. */
ssize_t
zreadcintr (fd, cp)
int fd;
char *cp;
{
ssize_t nr;
if (lind == lused || lused == 0)
{
nr = zreadintr (fd, lbuf, sizeof (lbuf));
lind = 0;
if (nr <= 0)
{
lused = 0;
return nr;
}
lused = nr;
}
if (cp)
*cp = lbuf[lind++];
return 1;
}
void
zreset ()
{
lind = lused = 0;
}
/* Sync the seek pointer for FD so that the kernel's idea of the last char
read is the last char returned by zreadc. */
void
zsyncfd (fd)
int fd;
{
off_t off, r;
off = lused - lind;
r = 0;
if (off > 0)
r = lseek (fd, -off, SEEK_CUR);
if (r >= 0)
lused = lind = 0;
}
+3
View File
@@ -3,4 +3,7 @@ Unless otherwise stated, all files in this directory are Copyright (C)
2004,2005,2006,2007,2008,2009,2010,2011
Free Software Foundation, Inc.
See the file COPYING in the bash distribution root directory for copying
and usage restrictions.
The file ifs-posix.tests is Copyright (C) 2005 Glen Fowler.
+1 -1
View File
@@ -1,4 +1,4 @@
BUILD_DIR=/usr/local/build/chet/bash/bash-current
BUILD_DIR=/usr/local/build/bash/bash-current
THIS_SH=$BUILD_DIR/bash
PATH=$PATH:$BUILD_DIR
+9
View File
@@ -0,0 +1,9 @@
BUILD_DIR=/usr/local/build/chet/bash/bash-current
THIS_SH=$BUILD_DIR/bash
PATH=$PATH:$BUILD_DIR
export THIS_SH PATH
rm -f /tmp/xx
/bin/sh "$@"