summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorChet Ramey <chet.ramey@case.edu>2014-02-26 09:36:43 -0500
committerChet Ramey <chet.ramey@case.edu>2014-02-26 09:36:43 -0500
commitac50fbac377e32b98d2de396f016ea81e8ee9961 (patch)
treef71882366b98fedf1a88a063103219a4935de926 /lib
parent4539d736f1aff232857a854fd2a68df0c98d9f34 (diff)
downloadbash-ac50fbac377e32b98d2de396f016ea81e8ee9961.tar.gz
Bash-4.3 distribution sources and documentationbash-4.3
Diffstat (limited to 'lib')
-rw-r--r--lib/glob/glob.c347
-rw-r--r--lib/glob/glob.h2
-rw-r--r--lib/glob/gmisc.c18
-rw-r--r--lib/glob/sm_loop.c55
-rw-r--r--lib/glob/smatch.c43
-rw-r--r--lib/glob/xmbsrtowcs.c17
-rw-r--r--lib/intl/Makefile.in6
-rw-r--r--lib/intl/l10nflist.c2
-rw-r--r--lib/intl/localealias.c5
-rw-r--r--lib/malloc/getpagesize.h2
-rw-r--r--lib/malloc/imalloc.h11
-rw-r--r--lib/malloc/malloc.c28
-rw-r--r--lib/malloc/table.c39
-rw-r--r--lib/readline/Makefile.in27
-rw-r--r--lib/readline/bind.c207
-rw-r--r--lib/readline/callback.c44
-rw-r--r--lib/readline/chardefs.h2
-rw-r--r--lib/readline/colors.c251
-rw-r--r--lib/readline/colors.h122
-rw-r--r--lib/readline/complete.c373
-rw-r--r--lib/readline/display.c336
-rw-r--r--lib/readline/doc/history.texi26
-rw-r--r--lib/readline/doc/hstech.texi4
-rw-r--r--lib/readline/doc/hsuser.texi24
-rw-r--r--lib/readline/doc/rlman.texi27
-rw-r--r--lib/readline/doc/rltech.texi210
-rw-r--r--lib/readline/doc/rluser.texi228
-rw-r--r--lib/readline/doc/rluserman.texi27
-rw-r--r--lib/readline/doc/version.texi12
-rw-r--r--lib/readline/examples/excallback.c7
-rw-r--r--lib/readline/examples/rl-callbacktest.c81
-rw-r--r--lib/readline/funmap.c5
-rw-r--r--lib/readline/histexpand.c70
-rw-r--r--lib/readline/histfile.c62
-rw-r--r--lib/readline/history.c8
-rw-r--r--lib/readline/history.h2
-rw-r--r--lib/readline/input.c53
-rw-r--r--lib/readline/isearch.c128
-rw-r--r--lib/readline/macro.c38
-rw-r--r--lib/readline/mbutil.c11
-rw-r--r--lib/readline/misc.c39
-rw-r--r--lib/readline/nls.c35
-rw-r--r--lib/readline/parse-colors.c440
-rw-r--r--lib/readline/parse-colors.h46
-rw-r--r--lib/readline/posixdir.h14
-rw-r--r--lib/readline/posixjmp.h2
-rw-r--r--lib/readline/readline.c154
-rw-r--r--lib/readline/readline.h36
-rw-r--r--lib/readline/rlconf.h12
-rw-r--r--lib/readline/rldefs.h10
-rw-r--r--lib/readline/rlmbutil.h9
-rw-r--r--lib/readline/rlprivate.h35
-rw-r--r--lib/readline/rlstdc.h12
-rw-r--r--lib/readline/rltty.c10
-rw-r--r--lib/readline/rltypedefs.h14
-rw-r--r--lib/readline/search.c93
-rw-r--r--lib/readline/shell.c48
-rw-r--r--lib/readline/signals.c120
-rw-r--r--lib/readline/terminal.c85
-rw-r--r--lib/readline/text.c7
-rw-r--r--lib/readline/undo.c39
-rw-r--r--lib/readline/util.c83
-rw-r--r--lib/readline/vi_keymap.c1
-rw-r--r--lib/readline/vi_mode.c100
-rw-r--r--lib/sh/Makefile.in45
-rw-r--r--lib/sh/casemod.c24
-rw-r--r--lib/sh/clktck.c4
-rw-r--r--lib/sh/eaccess.c13
-rw-r--r--lib/sh/fmtulong.c5
-rw-r--r--lib/sh/getcwd.c6
-rw-r--r--lib/sh/inet_aton.c2
-rw-r--r--lib/sh/itos.c12
-rw-r--r--lib/sh/mailstat.c2
-rw-r--r--lib/sh/makepath.c2
-rw-r--r--lib/sh/mbschr.c13
-rw-r--r--lib/sh/mktime.c2
-rw-r--r--lib/sh/oslib.c4
-rw-r--r--lib/sh/pathcanon.c2
-rw-r--r--lib/sh/pathphys.c4
-rw-r--r--lib/sh/shmbchar.c23
-rw-r--r--lib/sh/shquote.c109
-rw-r--r--lib/sh/snprintf.c178
-rw-r--r--lib/sh/spell.c2
-rw-r--r--lib/sh/strchrnul.c123
-rw-r--r--lib/sh/strdup.c42
-rw-r--r--lib/sh/strerror.c2
-rw-r--r--lib/sh/strftime.c155
-rw-r--r--lib/sh/stringvec.c16
-rw-r--r--lib/sh/strpbrk.c2
-rw-r--r--lib/sh/strtrans.c86
-rw-r--r--lib/sh/tmpfile.c6
-rw-r--r--lib/sh/unicode.c188
-rw-r--r--lib/sh/wcsnwidth.c56
-rw-r--r--lib/sh/zgetline.c2
-rw-r--r--lib/sh/zmapfd.c3
-rw-r--r--lib/sh/zread.c48
-rw-r--r--lib/tilde/shell.c17
97 files changed, 4529 insertions, 1073 deletions
diff --git a/lib/glob/glob.c b/lib/glob/glob.c
index ad9b9d90..f5494361 100644
--- a/lib/glob/glob.c
+++ b/lib/glob/glob.c
@@ -48,6 +48,8 @@
#include "stdc.h"
#include "memalloc.h"
+#include <signal.h>
+
#include "shell.h"
#include "glob.h"
@@ -84,6 +86,8 @@ struct globval
extern void throw_to_top_level __P((void));
extern int sh_eaccess __P((char *, int));
extern char *sh_makepath __P((const char *, const char *, int));
+extern int signal_is_pending __P((int));
+extern void run_pending_traps __P((void));
extern int extended_glob;
@@ -112,9 +116,13 @@ static void wdequote_pathname __P((char *));
# define dequote_pathname udequote_pathname
#endif
static void dequote_pathname __P((char *));
-static int glob_testdir __P((char *));
+static int glob_testdir __P((char *, int));
static char **glob_dir_to_array __P((char *, char **, int));
+/* Make sure these names continue to agree with what's in smatch.c */
+extern char *glob_patscan __P((char *, char *, int));
+extern wchar_t *glob_patscan_wc __P((wchar_t *, wchar_t *, int));
+
/* Compile `glob_loop.c' for single-byte characters. */
#define CHAR unsigned char
#define INT int
@@ -162,15 +170,67 @@ glob_pattern_p (pattern)
#endif
}
+#if EXTENDED_GLOB
+/* Return 1 if all subpatterns in the extended globbing pattern PAT indicate
+ that the name should be skipped. XXX - doesn't handle pattern negation,
+ not sure if it should */
+static int
+extglob_skipname (pat, dname, flags)
+ char *pat, *dname;
+ int flags;
+{
+ char *pp, *pe, *t;
+ int n, r;
+
+ pp = pat + 2;
+ pe = pp + strlen (pp) - 1; /*(*/
+ if (*pe != ')')
+ return 0;
+ if ((t = strchr (pp, '|')) == 0) /* easy case first */
+ {
+ *pe = '\0';
+ r = skipname (pp, dname, flags); /*(*/
+ *pe = ')';
+ return r;
+ }
+ while (t = glob_patscan (pp, pe, '|'))
+ {
+ n = t[-1];
+ t[-1] = '\0';
+ r = skipname (pp, dname, flags);
+ t[-1] = n;
+ if (r == 0) /* if any pattern says not skip, we don't skip */
+ return r;
+ pp = t;
+ } /*(*/
+
+ if (pp == pe) /* glob_patscan might find end of pattern */
+ return r;
+
+ *pe = '\0';
+# if defined (HANDLE_MULTIBYTE)
+ r = mbskipname (pp, dname, flags); /*(*/
+# else
+ r = skipname (pp, dname, flags); /*(*/
+# endif
+ *pe = ')';
+ return r;
+}
+#endif
+
/* Return 1 if DNAME should be skipped according to PAT. Mostly concerned
with matching leading `.'. */
-
static int
skipname (pat, dname, flags)
char *pat;
char *dname;
int flags;
{
+#if EXTENDED_GLOB
+ if (extglob_pattern_p (pat)) /* XXX */
+ return (extglob_skipname (pat, dname, flags));
+#endif
+
/* If a leading dot need not be explicitly matched, and the pattern
doesn't start with a `.', don't match `.' or `..' */
if (noglob_dot_filenames == 0 && pat[0] != '.' &&
@@ -179,7 +239,7 @@ skipname (pat, dname, flags)
(dname[1] == '\0' || (dname[1] == '.' && dname[2] == '\0'))))
return 1;
- /* If a dot must be explicity matched, check to see if they do. */
+ /* If a dot must be explicitly matched, check to see if they do. */
else if (noglob_dot_filenames && dname[0] == '.' && pat[0] != '.' &&
(pat[0] != '\\' || pat[1] != '.'))
return 1;
@@ -188,18 +248,91 @@ skipname (pat, dname, flags)
}
#if HANDLE_MULTIBYTE
+
+static int
+wchkname (pat_wc, dn_wc)
+ wchar_t *pat_wc, *dn_wc;
+{
+ /* If a leading dot need not be explicitly matched, and the
+ pattern doesn't start with a `.', don't match `.' or `..' */
+ if (noglob_dot_filenames == 0 && pat_wc[0] != L'.' &&
+ (pat_wc[0] != L'\\' || pat_wc[1] != L'.') &&
+ (dn_wc[0] == L'.' &&
+ (dn_wc[1] == L'\0' || (dn_wc[1] == L'.' && dn_wc[2] == L'\0'))))
+ return 1;
+
+ /* If a leading dot must be explicitly matched, check to see if the
+ pattern and dirname both have one. */
+ else if (noglob_dot_filenames && dn_wc[0] == L'.' &&
+ pat_wc[0] != L'.' &&
+ (pat_wc[0] != L'\\' || pat_wc[1] != L'.'))
+ return 1;
+
+ return 0;
+}
+
+static int
+wextglob_skipname (pat, dname, flags)
+ wchar_t *pat, *dname;
+ int flags;
+{
+#if EXTENDED_GLOB
+ wchar_t *pp, *pe, *t, n;
+ int r;
+
+ pp = pat + 2;
+ pe = pp + wcslen (pp) - 1; /*(*/
+ if (*pe != L')')
+ return 0;
+ if ((t = wcschr (pp, L'|')) == 0)
+ {
+ *pe = L'\0';
+ r = wchkname (pp, dname); /*(*/
+ *pe = L')';
+ return r;
+ }
+ while (t = glob_patscan_wc (pp, pe, '|'))
+ {
+ n = t[-1];
+ t[-1] = L'\0';
+ r = wchkname (pp, dname);
+ t[-1] = n;
+ if (r == 0)
+ return 0;
+ pp = t;
+ }
+
+ if (pp == pe) /* glob_patscan_wc might find end of pattern */
+ return r;
+
+ *pe = L'\0';
+ r = wchkname (pp, dname); /*(*/
+ *pe = L')';
+ return r;
+#else
+ return (wchkname (pat, dname));
+#endif
+}
+
/* Return 1 if DNAME should be skipped according to PAT. Handles multibyte
characters in PAT and DNAME. Mostly concerned with matching leading `.'. */
-
static int
mbskipname (pat, dname, flags)
char *pat, *dname;
int flags;
{
- int ret;
+ int ret, ext;
wchar_t *pat_wc, *dn_wc;
size_t pat_n, dn_n;
+ if (mbsmbchar (dname) == 0 && mbsmbchar (pat) == 0)
+ return (skipname (pat, dname, flags));
+
+ ext = 0;
+#if EXTENDED_GLOB
+ ext = extglob_pattern_p (pat);
+#endif
+
pat_wc = dn_wc = (wchar_t *)NULL;
pat_n = xdupmbstowcs (&pat_wc, NULL, pat);
@@ -208,22 +341,7 @@ mbskipname (pat, dname, flags)
ret = 0;
if (pat_n != (size_t)-1 && dn_n !=(size_t)-1)
- {
- /* If a leading dot need not be explicitly matched, and the
- pattern doesn't start with a `.', don't match `.' or `..' */
- if (noglob_dot_filenames == 0 && pat_wc[0] != L'.' &&
- (pat_wc[0] != L'\\' || pat_wc[1] != L'.') &&
- (dn_wc[0] == L'.' &&
- (dn_wc[1] == L'\0' || (dn_wc[1] == L'.' && dn_wc[2] == L'\0'))))
- ret = 1;
-
- /* If a leading dot must be explicity matched, check to see if the
- pattern and dirname both have one. */
- else if (noglob_dot_filenames && dn_wc[0] == L'.' &&
- pat_wc[0] != L'.' &&
- (pat_wc[0] != L'\\' || pat_wc[1] != L'.'))
- ret = 1;
- }
+ ret = ext ? wextglob_skipname (pat_wc, dn_wc, flags) : wchkname (pat_wc, dn_wc);
else
ret = skipname (pat, dname, flags);
@@ -325,13 +443,20 @@ dequote_pathname (pathname)
/* Return 0 if DIR is a directory, -1 otherwise. */
static int
-glob_testdir (dir)
+glob_testdir (dir, flags)
char *dir;
+ int flags;
{
struct stat finfo;
+ int r;
-/*itrace("glob_testdir: testing %s", dir);*/
- if (stat (dir, &finfo) < 0)
+/*itrace("glob_testdir: testing %s" flags = %d, dir, flags);*/
+#if defined (HAVE_LSTAT)
+ r = (flags & GX_ALLDIRS) ? lstat (dir, &finfo) : stat (dir, &finfo);
+#else
+ r = stat (dir, &finfo);
+#endif
+ if (r < 0)
return (-1);
if (S_ISDIR (finfo.st_mode) == 0)
@@ -407,7 +532,6 @@ finddirs (pat, sdir, flags, ep, np)
return ret;
}
-
/* Return a vector of names of files in directory DIR
whose names match glob pattern PAT.
@@ -456,7 +580,7 @@ glob_vector (pat, dir, flags)
/* If PAT is empty, skip the loop, but return one (empty) filename. */
if (pat == 0 || *pat == '\0')
{
- if (glob_testdir (dir) < 0)
+ if (glob_testdir (dir, 0) < 0)
return ((char **) &glob_error_return);
nextlink = (struct globval *)alloca (sizeof (struct globval));
@@ -478,7 +602,7 @@ glob_vector (pat, dir, flags)
skip = 1;
}
- patlen = strlen (pat);
+ patlen = (pat && *pat) ? strlen (pat) : 0;
/* If the filename pattern (PAT) does not contain any globbing characters,
we can dispense with reading the directory, and just see if there is
@@ -489,14 +613,18 @@ glob_vector (pat, dir, flags)
int dirlen;
struct stat finfo;
- if (glob_testdir (dir) < 0)
+ if (glob_testdir (dir, 0) < 0)
return ((char **) &glob_error_return);
dirlen = strlen (dir);
nextname = (char *)malloc (dirlen + patlen + 2);
npat = (char *)malloc (patlen + 1);
if (nextname == 0 || npat == 0)
- lose = 1;
+ {
+ FREE (nextname);
+ FREE (npat);
+ lose = 1;
+ }
else
{
strcpy (npat, pat);
@@ -518,7 +646,10 @@ glob_vector (pat, dir, flags)
count = 1;
}
else
- lose = 1;
+ {
+ free (npat);
+ lose = 1;
+ }
}
else
{
@@ -536,7 +667,7 @@ glob_vector (pat, dir, flags)
is not robust (i.e., it opens non-directories successfully), test
that DIR is a directory and punt if it's not. */
#if defined (OPENDIR_NOT_ROBUST)
- if (glob_testdir (dir) < 0)
+ if (glob_testdir (dir, 0) < 0)
return ((char **) &glob_error_return);
#endif
@@ -570,7 +701,12 @@ glob_vector (pat, dir, flags)
lose = 1;
break;
}
-
+ else if (signal_is_pending (SIGINT)) /* XXX - make SIGINT traps responsive */
+ {
+ lose = 1;
+ break;
+ }
+
dp = readdir (d);
if (dp == NULL)
break;
@@ -599,7 +735,7 @@ glob_vector (pat, dir, flags)
if (flags & GX_NULLDIR)
pflags |= MP_IGNDOT;
subdir = sh_makepath (dir, dp->d_name, pflags);
- isdir = glob_testdir (subdir);
+ isdir = glob_testdir (subdir, flags);
if (isdir < 0 && (flags & GX_MATCHDIRS))
{
free (subdir);
@@ -635,6 +771,8 @@ glob_vector (pat, dir, flags)
nextname = (char *) malloc (sdlen + 1);
if (nextlink == 0 || nextname == 0)
{
+ FREE (nextlink);
+ FREE (nextname);
free (subdir);
lose = 1;
break;
@@ -647,6 +785,8 @@ glob_vector (pat, dir, flags)
++count;
continue;
}
+ else if (flags & GX_MATCHDIRS)
+ free (subdir);
convfn = fnx_fromfs (dp->d_name, D_NAMLEN (dp));
if (strmatch (pat, convfn, mflags) != FNM_NOMATCH)
@@ -666,6 +806,8 @@ glob_vector (pat, dir, flags)
nextname = (char *) malloc (D_NAMLEN (dp) + 1);
if (nextlink == 0 || nextname == 0)
{
+ FREE (nextlink);
+ FREE (nextname);
lose = 1;
break;
}
@@ -689,7 +831,11 @@ glob_vector (pat, dir, flags)
nextname = (char *)malloc (sdlen + 1);
nextlink = (struct globval *) malloc (sizeof (struct globval));
if (nextlink == 0 || nextname == 0)
- lose = 1;
+ {
+ FREE (nextlink);
+ FREE (nextname);
+ lose = 1;
+ }
else
{
nextlink->name = nextname;
@@ -733,7 +879,7 @@ glob_vector (pat, dir, flags)
FREE (tmplink);
}
- QUIT;
+ /* Don't call QUIT; here; let higher layers deal with it. */
return ((char **)NULL);
}
@@ -815,7 +961,13 @@ glob_dir_to_array (dir, array, flags)
result[i] = (char *) malloc (l + strlen (array[i]) + 3);
if (result[i] == NULL)
- return (NULL);
+ {
+ int ind;
+ for (ind = 0; ind < i; ind++)
+ free (result[ind]);
+ free (result);
+ return (NULL);
+ }
strcpy (result[i], dir);
if (add_slash)
@@ -893,19 +1045,70 @@ glob_filename (pathname, flags)
/* If directory_name contains globbing characters, then we
have to expand the previous levels. Just recurse. */
- if (glob_pattern_p (directory_name))
+ if (directory_len > 0 && glob_pattern_p (directory_name))
{
- char **directories;
+ char **directories, *d, *p;
register unsigned int i;
+ int all_starstar, last_starstar;
+ all_starstar = last_starstar = 0;
+ d = directory_name;
dflags = flags & ~GX_MARKDIRS;
- if ((flags & GX_GLOBSTAR) && directory_name[0] == '*' && directory_name[1] == '*' && (directory_name[2] == '/' || directory_name[2] == '\0'))
- dflags |= GX_ALLDIRS|GX_ADDCURDIR;
+ /* Collapse a sequence of ** patterns separated by one or more slashes
+ to a single ** terminated by a slash or NUL */
+ if ((flags & GX_GLOBSTAR) && d[0] == '*' && d[1] == '*' && (d[2] == '/' || d[2] == '\0'))
+ {
+ p = d;
+ while (d[0] == '*' && d[1] == '*' && (d[2] == '/' || d[2] == '\0'))
+ {
+ p = d;
+ if (d[2])
+ {
+ d += 3;
+ while (*d == '/')
+ d++;
+ if (*d == 0)
+ break;
+ }
+ }
+ if (*d == 0)
+ all_starstar = 1;
+ d = p;
+ dflags |= GX_ALLDIRS|GX_ADDCURDIR;
+ directory_len = strlen (d);
+ }
+
+ /* If there is a non [star][star]/ component in directory_name, we
+ still need to collapse trailing sequences of [star][star]/ into
+ a single one and note that the directory name ends with [star][star],
+ so we can compensate if filename is [star][star] */
+ if ((flags & GX_GLOBSTAR) && all_starstar == 0)
+ {
+ int dl, prev;
+ prev = dl = directory_len;
+ while (dl >= 4 && d[dl - 1] == '/' &&
+ d[dl - 2] == '*' &&
+ d[dl - 3] == '*' &&
+ d[dl - 4] == '/')
+ prev = dl, dl -= 3;
+ if (dl != directory_len)
+ last_starstar = 1;
+ directory_len = prev;
+ }
+
+ /* If the directory name ends in [star][star]/ but the filename is
+ [star][star], just remove the final [star][star] from the directory
+ so we don't have to scan everything twice. */
+ if (last_starstar && directory_len > 4 &&
+ filename[0] == '*' && filename[1] == '*' && filename[2] == 0)
+ {
+ directory_len -= 3;
+ }
- if (directory_name[directory_len - 1] == '/')
- directory_name[directory_len - 1] = '\0';
+ if (d[directory_len - 1] == '/')
+ d[directory_len - 1] = '\0';
- directories = glob_filename (directory_name, dflags);
+ directories = glob_filename (d, dflags);
if (free_dirname)
{
@@ -927,13 +1130,26 @@ glob_filename (pathname, flags)
return ((char **) &glob_error_return);
}
+ /* If we have something like [star][star]/[star][star], it's no use to
+ glob **, then do it again, and throw half the results away. */
+ if (all_starstar && filename[0] == '*' && filename[1] == '*' && filename[2] == 0)
+ {
+ free ((char *) directories);
+ free (directory_name);
+ directory_name = NULL;
+ directory_len = 0;
+ goto only_filename;
+ }
+
/* We have successfully globbed the preceding directory name.
For each name in DIRECTORIES, call glob_vector on it and
FILENAME. Concatenate the results together. */
for (i = 0; directories[i] != NULL; ++i)
{
char **temp_results;
+ int shouldbreak;
+ shouldbreak = 0;
/* XXX -- we've recursively scanned any directories resulting from
a `**', so turn off the flag. We turn it on again below if
filename is `**' */
@@ -964,8 +1180,39 @@ glob_filename (pathname, flags)
/* If we're expanding **, we don't need to glue the directory
name to the results; we've already done it in glob_vector */
- if ((dflags & GX_ALLDIRS) && filename[0] == '*' && filename[1] == '*' && filename[2] == '\0')
- array = temp_results;
+ if ((dflags & GX_ALLDIRS) && filename[0] == '*' && filename[1] == '*' && (filename[2] == '\0' || filename[2] == '/'))
+ {
+ /* When do we remove null elements from temp_results? And
+ how to avoid duplicate elements in the final result? */
+ /* If (dflags & GX_NULLDIR) glob_filename potentially left a
+ NULL placeholder in the temp results just in case
+ glob_vector/glob_dir_to_array did something with it, but
+ if it didn't, and we're not supposed to be passing them
+ through for some reason ((flags & GX_NULLDIR) == 0) we
+ need to remove all the NULL elements from the beginning
+ of TEMP_RESULTS. */
+ /* If we have a null directory name and ** as the filename,
+ we have just searched for everything from the current
+ directory on down. Break now (shouldbreak = 1) to avoid
+ duplicate entries in the final result. */
+#define NULL_PLACEHOLDER(x) ((x) && *(x) && **(x) == 0)
+ if ((dflags & GX_NULLDIR) && (flags & GX_NULLDIR) == 0 &&
+ NULL_PLACEHOLDER (temp_results))
+#undef NULL_PLACEHOLDER
+ {
+ register int i, n;
+ for (n = 0; temp_results[n] && *temp_results[n] == 0; n++)
+ ;
+ i = n;
+ do
+ temp_results[i - n] = temp_results[i];
+ while (temp_results[i++] != 0);
+ array = temp_results;
+ shouldbreak = 1;
+ }
+ else
+ array = temp_results;
+ }
else
array = glob_dir_to_array (directories[i], temp_results, flags);
l = 0;
@@ -986,6 +1233,11 @@ glob_filename (pathname, flags)
/* Note that the elements of ARRAY are not freed. */
if (array != temp_results)
free ((char *) array);
+ else if ((dflags & GX_ALLDIRS) && filename[0] == '*' && filename[1] == '*' && filename[2] == '\0')
+ free (temp_results); /* expanding ** case above */
+
+ if (shouldbreak)
+ break;
}
}
/* Free the directories. */
@@ -997,6 +1249,7 @@ glob_filename (pathname, flags)
return (result);
}
+only_filename:
/* If there is only a directory name, return it. */
if (*filename == '\0')
{
@@ -1055,10 +1308,13 @@ glob_filename (pathname, flags)
{
if (free_dirname)
free (directory_name);
+ QUIT; /* XXX - shell */
+ run_pending_traps ();
return (temp_results);
}
result = glob_dir_to_array ((dflags & GX_ALLDIRS) ? "" : directory_name, temp_results, flags);
+
if (free_dirname)
free (directory_name);
return (result);
@@ -1079,6 +1335,7 @@ glob_filename (pathname, flags)
free (directory_name);
QUIT;
+ run_pending_traps ();
return (NULL);
}
diff --git a/lib/glob/glob.h b/lib/glob/glob.h
index 993ed70c..b9462333 100644
--- a/lib/glob/glob.h
+++ b/lib/glob/glob.h
@@ -35,6 +35,8 @@ extern int glob_pattern_p __P((const char *));
extern char **glob_vector __P((char *, char *, int));
extern char **glob_filename __P((char *, int));
+extern int extglob_pattern_p __P((const char *));
+
extern char *glob_error_return;
extern int noglob_dot_filenames;
extern int glob_ignore_case;
diff --git a/lib/glob/gmisc.c b/lib/glob/gmisc.c
index 683035a2..17e4265f 100644
--- a/lib/glob/gmisc.c
+++ b/lib/glob/gmisc.c
@@ -200,6 +200,24 @@ bad_bracket:
}
#endif
+int
+extglob_pattern_p (pat)
+ char *pat;
+{
+ switch (pat[0])
+ {
+ case '*':
+ case '+':
+ case '!':
+ case '@':
+ return (pat[1] == LPAREN);
+ default:
+ return 0;
+ }
+
+ return 0;
+}
+
/* Return 1 of the first character of STRING could match the first
character of pattern PAT. Used to avoid n2 calls to strmatch(). */
int
diff --git a/lib/glob/sm_loop.c b/lib/glob/sm_loop.c
index dfff06cf..7e7f538f 100644
--- a/lib/glob/sm_loop.c
+++ b/lib/glob/sm_loop.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2006 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2011 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -22,7 +22,8 @@ static int GMATCH __P((CHAR *, CHAR *, CHAR *, CHAR *, int));
static CHAR *PARSE_COLLSYM __P((CHAR *, INT *));
static CHAR *BRACKMATCH __P((CHAR *, U_CHAR, int));
static int EXTMATCH __P((INT, CHAR *, CHAR *, CHAR *, CHAR *, int));
-static CHAR *PATSCAN __P((CHAR *, CHAR *, INT));
+
+/*static*/ CHAR *PATSCAN __P((CHAR *, CHAR *, INT));
int
FCT (pattern, string, flags)
@@ -144,8 +145,9 @@ fprintf(stderr, "gmatch: pattern = %s; pe = %s\n", pattern, pe);
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;
+ /* We didn't match. If we have a `?(...)', we can match 0
+ or 1 times. */
+ return 0;
}
#endif
else if (c == L('?'))
@@ -191,6 +193,18 @@ fprintf(stderr, "gmatch: pattern = %s; pe = %s\n", pattern, pe);
if (p == pe && (c == L('?') || c == L('*')))
return (0);
+ /* If we've hit the end of the string and the rest of the pattern
+ is something that matches the empty string, we can succeed. */
+#if defined (EXTENDED_GLOB)
+ if (n == se && ((flags & FNM_EXTMATCH) && (c == L('!') || c == L('?')) && *p == L('(')))
+ {
+ --p;
+ if (EXTMATCH (c, n, se, p, pe, flags) == 0)
+ return (c == L('!') ? FNM_NOMATCH : 0);
+ return (c == L('!') ? 0 : FNM_NOMATCH);
+ }
+#endif
+
/* General case, use recursion. */
{
U_CHAR c1;
@@ -290,7 +304,7 @@ BRACKMATCH (p, test, flags)
{
register CHAR cstart, cend, c;
register int not; /* Nonzero if the sense of the character class is inverted. */
- int brcnt;
+ int brcnt, forcecoll;
INT pc;
CHAR *savep;
@@ -311,6 +325,7 @@ BRACKMATCH (p, test, flags)
/* Initialize cstart and cend in case `-' is the last
character of the pattern. */
cstart = cend = c;
+ forcecoll = 0;
/* POSIX.2 equivalence class: [=c=]. See POSIX.2 2.8.3.2. Find
the end of the equivalence class, move the pattern pointer past
@@ -400,6 +415,7 @@ BRACKMATCH (p, test, flags)
range. If it is, we set cstart to one greater than `test',
so any comparisons later will fail. */
cstart = (pc == INVALID) ? test + 1 : pc;
+ forcecoll = 1;
}
if (!(flags & FNM_NOESCAPE) && c == L('\\'))
@@ -443,6 +459,7 @@ BRACKMATCH (p, test, flags)
range expression. If we get one, we set cend to one fewer
than the test character to make sure the range test fails. */
cend = (pc == INVALID) ? test - 1 : pc;
+ forcecoll = 1;
}
cend = FOLD (cend);
@@ -453,7 +470,7 @@ BRACKMATCH (p, test, flags)
the expression shall be treated as invalid.'' Note that this
applies to only the range expression; the rest of the bracket
expression is still checked for matches. */
- if (RANGECMP (cstart, cend) > 0)
+ if (RANGECMP (cstart, cend, forcecoll) > 0)
{
if (c == L(']'))
break;
@@ -462,7 +479,7 @@ BRACKMATCH (p, test, flags)
}
}
- if (RANGECMP (test, cstart) >= 0 && RANGECMP (test, cend) <= 0)
+ if (RANGECMP (test, cstart, forcecoll) >= 0 && RANGECMP (test, cend, forcecoll) <= 0)
goto matched;
if (c == L(']'))
@@ -517,7 +534,7 @@ matched:
because we're scanning a `patlist'. Otherwise, we scan until we see
DELIM. In all cases, we never scan past END. The return value is the
first character after the matching DELIM. */
-static CHAR *
+/*static*/ CHAR *
PATSCAN (string, end, delim)
CHAR *string, *end;
INT delim;
@@ -530,6 +547,9 @@ PATSCAN (string, end, delim)
cchar = 0;
bfirst = NULL;
+ if (string == end)
+ return (NULL);
+
for (s = string; c = *s; s++)
{
if (s >= end)
@@ -606,19 +626,32 @@ STRCOMPARE (p, pe, s, se)
{
int ret;
CHAR c1, c2;
+ int l1, l2;
+
+ l1 = pe - p;
+ l2 = se - s;
+ if (l1 != l2)
+ return (FNM_NOMATCH); /* unequal lengths, can't be identical */
+
c1 = *pe;
c2 = *se;
- *pe = *se = '\0';
+ if (c1 != 0)
+ *pe = '\0';
+ if (c2 != 0)
+ *se = '\0';
+
#if HAVE_MULTIBYTE || defined (HAVE_STRCOLL)
ret = STRCOLL ((XCHAR *)p, (XCHAR *)s);
#else
ret = STRCMP ((XCHAR *)p, (XCHAR *)s);
#endif
- *pe = c1;
- *se = c2;
+ if (c1 != 0)
+ *pe = c1;
+ if (c2 != 0)
+ *se = c2;
return (ret == 0 ? ret : FNM_NOMATCH);
}
diff --git a/lib/glob/smatch.c b/lib/glob/smatch.c
index 061142be..848610ab 100644
--- a/lib/glob/smatch.c
+++ b/lib/glob/smatch.c
@@ -43,15 +43,25 @@
#define STREQ(a, b) ((a)[0] == (b)[0] && strcmp(a, b) == 0)
#define STREQN(a, b, n) ((a)[0] == (b)[0] && strncmp(a, b, n) == 0)
+#ifndef GLOBASCII_DEFAULT
+# define GLOBASCII_DEFAULT 0
+#endif
+
+int glob_asciirange = GLOBASCII_DEFAULT;
+
/* We use strcoll(3) for range comparisons in bracket expressions,
even though it can have unwanted side effects in locales
other than POSIX or US. For instance, in the de locale, [A-Z] matches
- all characters. */
+ all characters. If GLOB_ASCIIRANGE is non-zero, and we're not forcing
+ the use of strcoll (e.g., for explicit collating symbols), we use
+ straight ordering as if in the C locale. */
#if defined (HAVE_STRCOLL)
/* Helper function for collating symbol equivalence. */
-static int rangecmp (c1, c2)
+static int
+rangecmp (c1, c2, forcecoll)
int c1, c2;
+ int forcecoll;
{
static char s1[2] = { ' ', '\0' };
static char s2[2] = { ' ', '\0' };
@@ -64,6 +74,9 @@ static int rangecmp (c1, c2)
if (c1 == c2)
return (0);
+ if (forcecoll == 0 && glob_asciirange)
+ return (c1 - c2);
+
s1[0] = c1;
s2[0] = c2;
@@ -72,7 +85,7 @@ static int rangecmp (c1, c2)
return (c1 - c2);
}
#else /* !HAVE_STRCOLL */
-# define rangecmp(c1, c2) ((int)(c1) - (int)(c2))
+# define rangecmp(c1, c2, f) ((int)(c1) - (int)(c2))
#endif /* !HAVE_STRCOLL */
#if defined (HAVE_STRCOLL)
@@ -80,7 +93,7 @@ static int
collequiv (c1, c2)
int c1, c2;
{
- return (rangecmp (c1, c2) == 0);
+ return (rangecmp (c1, c2, 1) == 0);
}
#else
# define collequiv(c1, c2) ((c1) == (c2))
@@ -214,14 +227,14 @@ is_cclass (c, name)
#define COLLSYM collsym
#define PARSE_COLLSYM parse_collsym
#define BRACKMATCH brackmatch
-#define PATSCAN patscan
+#define PATSCAN glob_patscan
#define STRCOMPARE strcompare
#define EXTMATCH extmatch
#define STRCHR(S, C) strchr((S), (C))
#define STRCOLL(S1, S2) strcoll((S1), (S2))
#define STRLEN(S) strlen(S)
#define STRCMP(S1, S2) strcmp((S1), (S2))
-#define RANGECMP(C1, C2) rangecmp((C1), (C2))
+#define RANGECMP(C1, C2, F) rangecmp((C1), (C2), (F))
#define COLLEQUIV(C1, C2) collequiv((C1), (C2))
#define CTYPE_T enum char_class
#define IS_CCLASS(C, S) is_cclass((C), (S))
@@ -244,8 +257,9 @@ is_cclass (c, name)
extern char *mbsmbchar __P((const char *));
static int
-rangecmp_wc (c1, c2)
+rangecmp_wc (c1, c2, forcecoll)
wint_t c1, c2;
+ int forcecoll;
{
static wchar_t s1[2] = { L' ', L'\0' };
static wchar_t s2[2] = { L' ', L'\0' };
@@ -253,6 +267,9 @@ rangecmp_wc (c1, c2)
if (c1 == c2)
return 0;
+ if (forcecoll == 0 && glob_asciirange && c1 <= UCHAR_MAX && c2 <= UCHAR_MAX)
+ return ((int)(c1 - c2));
+
s1[0] = c1;
s2[0] = c2;
@@ -263,7 +280,7 @@ static int
collequiv_wc (c, equiv)
wint_t c, equiv;
{
- return (!(c - equiv));
+ return (c == equiv);
}
/* Helper function for collating symbol. */
@@ -342,14 +359,14 @@ is_wcclass (wc, name)
#define COLLSYM collwcsym
#define PARSE_COLLSYM parse_collwcsym
#define BRACKMATCH brackmatch_wc
-#define PATSCAN patscan_wc
+#define PATSCAN glob_patscan_wc
#define STRCOMPARE wscompare
#define EXTMATCH extmatch_wc
#define STRCHR(S, C) wcschr((S), (C))
#define STRCOLL(S1, S2) wcscoll((S1), (S2))
#define STRLEN(S) wcslen(S)
#define STRCMP(S1, S2) wcscmp((S1), (S2))
-#define RANGECMP(C1, C2) rangecmp_wc((C1), (C2))
+#define RANGECMP(C1, C2, F) rangecmp_wc((C1), (C2), (F))
#define COLLEQUIV(C1, C2) collequiv_wc((C1), (C2))
#define CTYPE_T enum char_class
#define IS_CCLASS(C, S) is_wcclass((C), (S))
@@ -369,13 +386,7 @@ xstrmatch (pattern, string, flags)
wchar_t *wpattern, *wstring;
size_t plen, slen, mplen, mslen;
-#if 0
- plen = strlen (pattern);
- mplen = mbstrlen (pattern);
- if (plen == mplen && strlen (string) == mbstrlen (string))
-#else
if (mbsmbchar (string) == 0 && mbsmbchar (pattern) == 0)
-#endif
return (internal_strmatch ((unsigned char *)pattern, (unsigned char *)string, flags));
if (MB_CUR_MAX == 1)
diff --git a/lib/glob/xmbsrtowcs.c b/lib/glob/xmbsrtowcs.c
index c410e05a..11a4d1b9 100644
--- a/lib/glob/xmbsrtowcs.c
+++ b/lib/glob/xmbsrtowcs.c
@@ -1,6 +1,6 @@
/* xmbsrtowcs.c -- replacement function for mbsrtowcs */
-/* Copyright (C) 2002-2010 Free Software Foundation, Inc.
+/* Copyright (C) 2002-2013 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -166,7 +166,7 @@ xdupmbstowcs2 (destp, src)
do
{
end_or_backslash = strchrnul(p, '\\');
- nms = (end_or_backslash - p);
+ nms = end_or_backslash - p;
if (*end_or_backslash == '\0')
nms++;
@@ -283,6 +283,8 @@ xdupmbstowcs (destp, indicesp, src)
{
if (destp)
*destp = NULL;
+ if (indicesp)
+ *indicesp = NULL;
return (size_t)-1;
}
@@ -298,6 +300,8 @@ xdupmbstowcs (destp, indicesp, src)
if (wsbuf == NULL)
{
*destp = NULL;
+ if (indicesp)
+ *indicesp = NULL;
return (size_t)-1;
}
@@ -309,6 +313,7 @@ xdupmbstowcs (destp, indicesp, src)
{
free (wsbuf);
*destp = NULL;
+ *indicesp = NULL;
return (size_t)-1;
}
}
@@ -343,6 +348,8 @@ xdupmbstowcs (destp, indicesp, src)
free (wsbuf);
FREE (indices);
*destp = NULL;
+ if (indicesp)
+ *indicesp = NULL;
return (size_t)-1;
}
@@ -362,18 +369,22 @@ xdupmbstowcs (destp, indicesp, src)
free (wsbuf);
FREE (indices);
*destp = NULL;
+ if (indicesp)
+ *indicesp = NULL;
return (size_t)-1;
}
wsbuf = wstmp;
if (indicesp)
{
- idxtmp = (char **) realloc (indices, wsbuf_size * sizeof (char **));
+ idxtmp = (char **) realloc (indices, wsbuf_size * sizeof (char *));
if (idxtmp == NULL)
{
free (wsbuf);
free (indices);
*destp = NULL;
+ if (indicesp)
+ *indicesp = NULL;
return (size_t)-1;
}
indices = idxtmp;
diff --git a/lib/intl/Makefile.in b/lib/intl/Makefile.in
index c5245d4c..00fdb612 100644
--- a/lib/intl/Makefile.in
+++ b/lib/intl/Makefile.in
@@ -49,13 +49,15 @@ mkinstalldirs = $(SHELL) $(MKINSTALLDIRS)
l = @INTL_LIBTOOL_SUFFIX_PREFIX@
-AR = ar
+AR = @AR@
CC = @CC@
LIBTOOL = @LIBTOOL@
RANLIB = @RANLIB@
YACC = @INTLBISON@ -y -d
YFLAGS = --name-prefix=__gettext
+ARFLAGS = @ARFLAGS@
+
LOCAL_DEFS = @LOCAL_DEFS@
DEFS = -DLOCALEDIR=\"$(localedir)\" -DLOCALE_ALIAS_PATH=\"$(aliaspath)\" \
@@ -146,7 +148,7 @@ all-no-no:
libintl.a libgnuintl.a: $(OBJECTS)
rm -f $@
- $(AR) cru $@ $(OBJECTS)
+ $(AR) $(ARFLAGS) $@ $(OBJECTS)
$(RANLIB) $@
libintl.la libgnuintl.la: $(OBJECTS)
diff --git a/lib/intl/l10nflist.c b/lib/intl/l10nflist.c
index 9f024871..7556c8cd 100644
--- a/lib/intl/l10nflist.c
+++ b/lib/intl/l10nflist.c
@@ -272,7 +272,7 @@ _nl_make_l10nflist (l10nfile_list, dirlist, dirlist_len, mask, language,
}
if ((mask & (XPG_MODIFIER | CEN_AUDIENCE)) != 0)
{
- /* This component can be part of both syntaces but has different
+ /* This component can be part of both syntaxes but has different
leading characters. For CEN we use `+', else `@'. */
*cp++ = (mask & CEN_AUDIENCE) != 0 ? '+' : '@';
cp = stpcpy (cp, modifier);
diff --git a/lib/intl/localealias.c b/lib/intl/localealias.c
index d99a48d9..0d5ded71 100644
--- a/lib/intl/localealias.c
+++ b/lib/intl/localealias.c
@@ -305,7 +305,10 @@ read_alias_file (fname, fname_len)
if (nmap >= maxmap)
if (__builtin_expect (extend_alias_table (), 0))
- return added;
+ {
+ fclose (fp);
+ return added;
+ }
alias_len = strlen (alias) + 1;
value_len = strlen (value) + 1;
diff --git a/lib/malloc/getpagesize.h b/lib/malloc/getpagesize.h
index 7f323400..a59eabeb 100644
--- a/lib/malloc/getpagesize.h
+++ b/lib/malloc/getpagesize.h
@@ -32,7 +32,7 @@
#endif
#if !defined (getpagesize)
-# ifndef _MINIX
+# if defined (HAVE_SYS_PARAM_H)
# include <sys/param.h>
# endif
# if defined (PAGESIZE)
diff --git a/lib/malloc/imalloc.h b/lib/malloc/imalloc.h
index 34df10af..82b09eba 100644
--- a/lib/malloc/imalloc.h
+++ b/lib/malloc/imalloc.h
@@ -45,11 +45,11 @@
# define NULL 0
#endif
-#if !defined (__STRING)
+#if !defined (CPP_STRING)
# if defined (HAVE_STRINGIZE)
-# define __STRING(x) #x
+# define CPP_STRING(x) #x
# else
-# define __STRING(x) "x"
+# define CPP_STRING(x) "x"
# endif /* !HAVE_STRINGIZE */
#endif /* !__STRING */
@@ -165,4 +165,9 @@ do { \
# define _(x) x
#endif
+#include <signal.h>
+
+extern void _malloc_block_signals __P((sigset_t *, sigset_t *));
+extern void _malloc_unblock_signals __P((sigset_t *, sigset_t *));
+
#endif /* _IMALLOC_H */
diff --git a/lib/malloc/malloc.c b/lib/malloc/malloc.c
index bca68e8a..cd987c0d 100644
--- a/lib/malloc/malloc.c
+++ b/lib/malloc/malloc.c
@@ -172,7 +172,7 @@ typedef union _malloc_guard {
#define ASSERT(p) \
do \
{ \
- if (!(p)) xbotch((PTR_T)0, ERR_ASSERT_FAILED, __STRING(p), file, line); \
+ if (!(p)) xbotch((PTR_T)0, ERR_ASSERT_FAILED, CPP_STRING(p), file, line); \
} \
while (0)
@@ -265,7 +265,7 @@ extern char *sbrk ();
#endif /* !HAVE_DECL_SBRK */
#ifdef SHELL
-extern int interrupt_immediately;
+extern int interrupt_immediately, running_trap;
extern int signal_is_trapped __P((int));
#endif
@@ -498,8 +498,8 @@ xsplit (mp, nu)
busy[nbuck] = 0;
}
-static void
-block_signals (setp, osetp)
+void
+_malloc_block_signals (setp, osetp)
sigset_t *setp, *osetp;
{
#ifdef HAVE_POSIX_SIGNALS
@@ -513,8 +513,8 @@ block_signals (setp, osetp)
#endif
}
-static void
-unblock_signals (setp, osetp)
+void
+_malloc_unblock_signals (setp, osetp)
sigset_t *setp, *osetp;
{
#ifdef HAVE_POSIX_SIGNALS
@@ -562,10 +562,14 @@ morecore (nu)
/* Block all signals in case we are executed from a signal handler. */
blocked_sigs = 0;
#ifdef SHELL
- if (interrupt_immediately || signal_is_trapped (SIGINT) || signal_is_trapped (SIGCHLD))
+# if defined (SIGCHLD)
+ if (interrupt_immediately || running_trap || signal_is_trapped (SIGINT) || signal_is_trapped (SIGCHLD))
+# else
+ if (interrupt_immediately || running_trap || signal_is_trapped (SIGINT))
+# endif
#endif
{
- block_signals (&set, &oset);
+ _malloc_block_signals (&set, &oset);
blocked_sigs = 1;
}
@@ -652,7 +656,7 @@ morecore (nu)
morecore_done:
if (blocked_sigs)
- unblock_signals (&set, &oset);
+ _malloc_unblock_signals (&set, &oset);
}
static void
@@ -901,10 +905,10 @@ internal_free (mem, file, line, flags)
if (mg.i != p->mh_nbytes)
xbotch (mem, ERR_ASSERT_FAILED, _("free: start and end chunk sizes differ"), file, line);
-#if 1
- if (nunits >= LESSCORE_MIN && ((char *)p + binsize(nunits) == memtop))
+#if GLIBC21
+ if (nunits >= LESSCORE_MIN && ((char *)p + binsize(nunits) == sbrk (0)))
#else
- if (((char *)p + binsize(nunits) == memtop) && nunits >= LESSCORE_MIN)
+ if (nunits >= LESSCORE_MIN && ((char *)p + binsize(nunits) == memtop))
#endif
{
/* If above LESSCORE_FRC, give back unconditionally. This should be set
diff --git a/lib/malloc/table.c b/lib/malloc/table.c
index cf89b3c0..dfa29e22 100644
--- a/lib/malloc/table.c
+++ b/lib/malloc/table.c
@@ -28,6 +28,11 @@
#include "imalloc.h"
#include "table.h"
+#ifdef SHELL
+extern int interrupt_immediately, running_trap;
+extern int signal_is_trapped __P((int));
+#endif
+
extern int malloc_register;
#ifdef MALLOC_REGISTER
@@ -168,6 +173,18 @@ mregister_alloc (tag, mem, size, file, line)
int line;
{
mr_table_t *tentry;
+ sigset_t set, oset;
+ int blocked_sigs;
+
+ /* Block all signals in case we are executed from a signal handler. */
+ blocked_sigs = 0;
+#ifdef SHELL
+ if (interrupt_immediately || running_trap || signal_is_trapped (SIGINT) || signal_is_trapped (SIGCHLD))
+#endif
+ {
+ _malloc_block_signals (&set, &oset);
+ blocked_sigs = 1;
+ }
tentry = find_entry (mem, FIND_ALLOC);
@@ -175,6 +192,8 @@ mregister_alloc (tag, mem, size, file, line)
{
/* oops. table is full. punt. */
fprintf (stderr, _("register_alloc: alloc table is full with FIND_ALLOC?\n"));
+ if (blocked_sigs)
+ _malloc_unblock_signals (&set, &oset);
return;
}
@@ -194,6 +213,9 @@ mregister_alloc (tag, mem, size, file, line)
if (tentry != &mem_overflow)
table_allocated++;
+
+ if (blocked_sigs)
+ _malloc_unblock_signals (&set, &oset);
}
void
@@ -204,6 +226,18 @@ mregister_free (mem, size, file, line)
int line;
{
mr_table_t *tentry;
+ sigset_t set, oset;
+ int blocked_sigs;
+
+ /* Block all signals in case we are executed from a signal handler. */
+ blocked_sigs = 0;
+#ifdef SHELL
+ if (interrupt_immediately || running_trap || signal_is_trapped (SIGINT) || signal_is_trapped (SIGCHLD))
+#endif
+ {
+ _malloc_block_signals (&set, &oset);
+ blocked_sigs = 1;
+ }
tentry = find_entry (mem, FIND_EXIST);
if (tentry == 0)
@@ -212,6 +246,8 @@ mregister_free (mem, size, file, line)
#if 0
fprintf (stderr, "register_free: %p not in allocation table?\n", mem);
#endif
+ if (blocked_sigs)
+ _malloc_unblock_signals (&set, &oset);
return;
}
if (tentry->flags & MT_FREE)
@@ -228,6 +264,9 @@ mregister_free (mem, size, file, line)
if (tentry != &mem_overflow)
table_allocated--;
+
+ if (blocked_sigs)
+ _malloc_unblock_signals (&set, &oset);
}
/* If we ever add more flags, this will require changes. */
diff --git a/lib/readline/Makefile.in b/lib/readline/Makefile.in
index 4387a54e..acccd021 100644
--- a/lib/readline/Makefile.in
+++ b/lib/readline/Makefile.in
@@ -4,7 +4,7 @@
# #
#############################################################################
-# Copyright (C) 1994-2009 Free Software Foundation, Inc.
+# Copyright (C) 1994-2012 Free Software Foundation, Inc.
# 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
@@ -83,21 +83,24 @@ CSOURCES = $(srcdir)/readline.c $(srcdir)/funmap.c $(srcdir)/keymaps.c \
$(srcdir)/histfile.c $(srcdir)/nls.c $(srcdir)/search.c \
$(srcdir)/shell.c $(srcdir)/tilde.c $(srcdir)/savestring.c \
$(srcdir)/text.c $(srcdir)/misc.c $(srcdir)/compat.c \
+ $(srcdir)/colors.c $(srcdir)/parse-colors.c \
$(srcdir)/mbutil.c $(srcdir)/xfree.c
# The header files for this library.
HSOURCES = readline.h rldefs.h chardefs.h keymaps.h history.h histlib.h \
posixstat.h posixdir.h posixjmp.h tilde.h rlconf.h rltty.h \
ansi_stdlib.h rlstdc.h tcap.h xmalloc.h rlprivate.h rlshell.h \
- rltypedefs.h rlmbutil.h
+ rltypedefs.h rlmbutil.h colors.h parse-colors.h
HISTOBJ = history.o histexpand.o histfile.o histsearch.o shell.o savestring.o \
mbutil.o
TILDEOBJ = tilde.o
+COLORSOBJ = colors.o parse-colors.o
OBJECTS = readline.o vi_mode.o funmap.o keymaps.o parens.o search.o \
rltty.o complete.o bind.o isearch.o display.o signals.o \
util.o kill.o undo.o macro.o input.o callback.o terminal.o \
- text.o nls.o misc.o $(HISTOBJ) $(TILDEOBJ) xmalloc.o xfree.o compat.o
+ text.o nls.o misc.o $(HISTOBJ) $(TILDEOBJ) $(COLORSOBJ) \
+ xmalloc.o xfree.o compat.o
# The texinfo files which document this library.
DOCSOURCE = doc/rlman.texinfo doc/rltech.texinfo doc/rluser.texinfo
@@ -176,6 +179,7 @@ compat.o: rlstdc.h
complete.o: ansi_stdlib.h posixdir.h posixstat.h
complete.o: rldefs.h ${BUILD_DIR}/config.h rlconf.h
complete.o: readline.h keymaps.h rltypedefs.h chardefs.h tilde.h rlstdc.h
+complete.o: colors.h
display.o: ansi_stdlib.h posixstat.h
display.o: rldefs.h ${BUILD_DIR}/config.h rlconf.h
display.o: tcap.h
@@ -264,6 +268,14 @@ vi_mode.o: history.h ansi_stdlib.h rlstdc.h
xmalloc.o: ${BUILD_DIR}/config.h ansi_stdlib.h
xfree.o: ${BUILD_DIR}/config.h ansi_stdlib.h
+colors.o: ${BUILD_DIR}/config.h colors.h
+colors.o: readline.h keymaps.h rltypedefs.h chardefs.h tilde.h rlstdc.h
+colors.o: rlconf.h
+colors.o: ansi_stdlib.h posixstat.h
+parse-colors.o: ${BUILD_DIR}/config.h colors.h parse-colors.h
+parse-colors.o: rldefs.h rlconf.h
+parse-colors.o: readline.h keymaps.h rltypedefs.h chardefs.h tilde.h rlstdc.h
+
bind.o: rlshell.h
histfile.o: rlshell.h
nls.o: rlshell.h
@@ -293,6 +305,8 @@ text.o: rlprivate.h
undo.o: rlprivate.h
util.o: rlprivate.h
vi_mode.o: rlprivate.h
+colors.o: rlprivate.h
+parse-colors.o: rlprivate.h
bind.o: xmalloc.h
complete.o: xmalloc.h
@@ -320,6 +334,8 @@ util.o: xmalloc.h
vi_mode.o: xmalloc.h
xfree.o: xmalloc.h
xmalloc.o: xmalloc.h
+colors.o: xmalloc.h
+parse-colors.o: xmalloc.h
complete.o: rlmbutil.h
display.o: rlmbutil.h
@@ -332,6 +348,8 @@ readline.o: rlmbutil.h
search.o: rlmbutil.h
text.o: rlmbutil.h
vi_mode.o: rlmbutil.h
+colors.o: rlmbutil.h
+parse-colors.o: rlmbutil.h
# Rules for deficient makes, like SunOS and Solaris
bind.o: bind.c
@@ -364,6 +382,9 @@ vi_mode.o: vi_mode.c
xfree.o: xfree.c
xmalloc.o: xmalloc.c
+colors.o: colors.c
+parse-colors.o: parse-colors.c
+
histexpand.o: histexpand.c
histfile.o: histfile.c
history.o: history.c
diff --git a/lib/readline/bind.c b/lib/readline/bind.c
index 59e79643..8acf4ac4 100644
--- a/lib/readline/bind.c
+++ b/lib/readline/bind.c
@@ -1,6 +1,6 @@
/* bind.c -- key binding and startup file support for the readline library. */
-/* Copyright (C) 1987-2010 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2012 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.
@@ -72,11 +72,15 @@ extern char *strchr (), *strrchr ();
/* Variables exported by this file. */
Keymap rl_binding_keymap;
+static int _rl_skip_to_delim PARAMS((char *, int, int));
+
static char *_rl_read_file PARAMS((char *, size_t *));
static void _rl_init_file_error PARAMS((const char *));
static int _rl_read_init_file PARAMS((const char *, int));
static int glean_key_from_name PARAMS((char *));
+
static int find_boolean_var PARAMS((const char *));
+static int find_string_var PARAMS((const char *));
static char *_rl_get_string_variable_value PARAMS((const char *));
static int substring_member_of_array PARAMS((const char *, const char * const *));
@@ -567,6 +571,40 @@ rl_translate_keyseq (seq, array, len)
return (0);
}
+static int
+_rl_isescape (c)
+ int c;
+{
+ switch (c)
+ {
+ case '\007':
+ case '\b':
+ case '\f':
+ case '\n':
+ case '\r':
+ case TAB:
+ case 0x0b: return (1);
+ default: return (0);
+ }
+}
+
+static int
+_rl_escchar (c)
+ int c;
+{
+ switch (c)
+ {
+ case '\007': return ('a');
+ case '\b': return ('b');
+ case '\f': return ('f');
+ case '\n': return ('n');
+ case '\r': return ('r');
+ case TAB: return ('t');
+ case 0x0b: return ('v');
+ default: return (c);
+ }
+}
+
char *
rl_untranslate_keyseq (seq)
int seq;
@@ -618,9 +656,10 @@ rl_untranslate_keyseq (seq)
return kseq;
}
-static char *
-_rl_untranslate_macro_value (seq)
+char *
+_rl_untranslate_macro_value (seq, use_escapes)
char *seq;
+ int use_escapes;
{
char *ret, *r, *s;
int c;
@@ -644,9 +683,14 @@ _rl_untranslate_macro_value (seq)
else if (CTRL_CHAR (c))
{
*r++ = '\\';
- *r++ = 'C';
- *r++ = '-';
- c = _rl_to_lower (UNCTRL (c));
+ if (use_escapes && _rl_isescape (c))
+ c = _rl_escchar (c);
+ else
+ {
+ *r++ = 'C';
+ *r++ = '-';
+ c = _rl_to_lower (UNCTRL (c));
+ }
}
else if (c == RUBOUT)
{
@@ -1157,6 +1201,38 @@ handle_parser_directive (statement)
return (1);
}
+/* Start at STRING[START] and look for DELIM. Return I where STRING[I] ==
+ DELIM or STRING[I] == 0. DELIM is usually a double quote. */
+static int
+_rl_skip_to_delim (string, start, delim)
+ char *string;
+ int start, delim;
+{
+ int i, c, passc;
+
+ for (i = start,passc = 0; c = string[i]; i++)
+ {
+ if (passc)
+ {
+ passc = 0;
+ if (c == 0)
+ break;
+ continue;
+ }
+
+ if (c == '\\')
+ {
+ passc = 1;
+ continue;
+ }
+
+ if (c == delim)
+ break;
+ }
+
+ return i;
+}
+
/* Read the binding command from STRING and perform it.
A key binding command looks like: Keyname: function-name\0,
a variable binding command looks like: set variable value.
@@ -1172,7 +1248,7 @@ rl_parse_and_bind (string)
while (string && whitespace (*string))
string++;
- if (!string || !*string || *string == '#')
+ if (string == 0 || *string == 0 || *string == '#')
return 0;
/* If this is a parser directive, act on it. */
@@ -1192,31 +1268,16 @@ rl_parse_and_bind (string)
backslash to quote characters in the key expression. */
if (*string == '"')
{
- int passc = 0;
+ i = _rl_skip_to_delim (string, 1, '"');
- for (i = 1; c = string[i]; i++)
- {
- if (passc)
- {
- passc = 0;
- continue;
- }
-
- if (c == '\\')
- {
- passc++;
- continue;
- }
-
- if (c == '"')
- break;
- }
/* If we didn't find a closing quote, abort the line. */
if (string[i] == '\0')
{
_rl_init_file_error ("no closing `\"' in key binding");
return 1;
}
+ else
+ i++; /* skip past closing double quote */
}
/* Advance to the colon (:) or whitespace which separates the two objects. */
@@ -1236,6 +1297,7 @@ rl_parse_and_bind (string)
if (_rl_stricmp (string, "set") == 0)
{
char *var, *value, *e;
+ int s;
var = string + i;
/* Make VAR point to start of variable name. */
@@ -1243,25 +1305,37 @@ rl_parse_and_bind (string)
/* Make VALUE point to start of value string. */
value = var;
- while (*value && !whitespace (*value)) value++;
+ while (*value && whitespace (*value) == 0) value++;
if (*value)
*value++ = '\0';
while (*value && whitespace (*value)) value++;
- /* Strip trailing whitespace from values to boolean variables. Temp
- fix until I get a real quoted-string parser here. */
- i = find_boolean_var (var);
- if (i >= 0)
+ /* Strip trailing whitespace from values of boolean variables. */
+ if (find_boolean_var (var) >= 0)
{
/* remove trailing whitespace */
+remove_trailing:
e = value + strlen (value) - 1;
while (e >= value && whitespace (*e))
e--;
e++; /* skip back to whitespace or EOS */
+
if (*e && e >= value)
*e = '\0';
}
-
+ else if ((i = find_string_var (var)) >= 0)
+ {
+ /* Allow quoted strings in variable values */
+ if (*value == '"')
+ {
+ i = _rl_skip_to_delim (value, 1, *value);
+ value[i] = '\0';
+ value++; /* skip past the quote */
+ }
+ else
+ goto remove_trailing;
+ }
+
rl_variable_bind (var, value);
return 0;
}
@@ -1282,32 +1356,13 @@ rl_parse_and_bind (string)
the quoted string delimiter, like the shell. */
if (*funname == '\'' || *funname == '"')
{
- int delimiter, passc;
-
- delimiter = string[i++];
- for (passc = 0; c = string[i]; i++)
- {
- if (passc)
- {
- passc = 0;
- continue;
- }
-
- if (c == '\\')
- {
- passc = 1;
- continue;
- }
-
- if (c == delimiter)
- break;
- }
- if (c)
+ i = _rl_skip_to_delim (string, i+1, *funname);
+ if (string[i])
i++;
}
/* Advance to the end of the string. */
- for (; string[i] && !whitespace (string[i]); i++);
+ for (; string[i] && whitespace (string[i]) == 0; i++);
/* No extra whitespace at the end of the string. */
string[i] = '\0';
@@ -1367,7 +1422,7 @@ rl_parse_and_bind (string)
/* Get the actual character we want to deal with. */
kname = strrchr (string, '-');
- if (!kname)
+ if (kname == 0)
kname = string;
else
kname++;
@@ -1423,6 +1478,9 @@ static const struct {
{ "bind-tty-special-chars", &_rl_bind_stty_chars, 0 },
{ "blink-matching-paren", &rl_blink_matching_paren, V_SPECIAL },
{ "byte-oriented", &rl_byte_oriented, 0 },
+#if defined (COLOR_SUPPORT)
+ { "colored-stats", &_rl_colored_stats, 0 },
+#endif
{ "completion-ignore-case", &_rl_completion_case_fold, 0 },
{ "completion-map-case", &_rl_completion_case_map, 0 },
{ "convert-meta", &_rl_convert_meta_chars_to_ascii, 0 },
@@ -1447,6 +1505,7 @@ static const struct {
{ "revert-all-at-newline", &_rl_revert_all_at_newline, 0 },
{ "show-all-if-ambiguous", &_rl_complete_show_all, 0 },
{ "show-all-if-unmodified", &_rl_complete_show_unmodified, 0 },
+ { "show-mode-in-prompt", &_rl_show_mode_in_prompt, 0 },
{ "skip-completed-text", &_rl_skip_completed_text, 0 },
#if defined (VISIBLE_STATS)
{ "visible-stats", &rl_visible_stats, 0 },
@@ -1486,6 +1545,8 @@ hack_special_boolean_var (i)
else
_rl_bell_preference = AUDIBLE_BELL;
}
+ else if (_rl_stricmp (name, "show-mode-in-prompt") == 0)
+ _rl_reset_prompt ();
}
typedef int _rl_sv_func_t PARAMS((const char *));
@@ -1511,6 +1572,7 @@ static int sv_editmode PARAMS((const char *));
static int sv_histsize PARAMS((const char *));
static int sv_isrchterm PARAMS((const char *));
static int sv_keymap PARAMS((const char *));
+static int sv_seqtimeout PARAMS((const char *));
static const struct {
const char * const name;
@@ -1526,6 +1588,7 @@ static const struct {
{ "history-size", V_INT, sv_histsize },
{ "isearch-terminators", V_STRING, sv_isrchterm },
{ "keymap", V_STRING, sv_keymap },
+ { "keyseq-timeout", V_INT, sv_seqtimeout },
{ (char *)NULL, 0, (_rl_sv_func_t *)0 }
};
@@ -1683,13 +1746,17 @@ static int
sv_histsize (value)
const char *value;
{
- int nval = 500;
+ int nval;
+ nval = 500;
if (value && *value)
{
nval = atoi (value);
if (nval < 0)
- return 1;
+ {
+ unstifle_history ();
+ return 0;
+ }
}
stifle_history (nval);
return 0;
@@ -1711,6 +1778,23 @@ sv_keymap (value)
}
static int
+sv_seqtimeout (value)
+ const char *value;
+{
+ int nval;
+
+ nval = 0;
+ if (value && *value)
+ {
+ nval = atoi (value);
+ if (nval < 0)
+ nval = 0;
+ }
+ _rl_keyseq_timeout = nval;
+ return 0;
+}
+
+static int
sv_bell_style (value)
const char *value;
{
@@ -2167,6 +2251,8 @@ rl_function_dumper (print_readably)
}
}
}
+
+ xfree (names);
}
/* Print all of the current functions and their bindings to
@@ -2199,7 +2285,7 @@ _rl_macro_dumper_internal (print_readably, map, prefix)
{
case ISMACR:
keyname = _rl_get_keyname (key);
- out = _rl_untranslate_macro_value ((char *)map[key].function);
+ out = _rl_untranslate_macro_value ((char *)map[key].function, 0);
if (print_readably)
fprintf (rl_outstream, "\"%s%s\": \"%s\"\n", prefix ? prefix : "",
@@ -2311,7 +2397,7 @@ _rl_get_string_variable_value (name)
{
if (_rl_isearch_terminators == 0)
return 0;
- ret = _rl_untranslate_macro_value (_rl_isearch_terminators);
+ ret = _rl_untranslate_macro_value (_rl_isearch_terminators, 0);
if (ret)
{
strncpy (numbuf, ret, sizeof (numbuf) - 1);
@@ -2329,6 +2415,11 @@ _rl_get_string_variable_value (name)
ret = rl_get_keymap_name_from_edit_mode ();
return (ret ? ret : "none");
}
+ else if (_rl_stricmp (name, "keyseq-timeout") == 0)
+ {
+ sprintf (numbuf, "%d", _rl_keyseq_timeout);
+ return (numbuf);
+ }
else
return (0);
}
diff --git a/lib/readline/callback.c b/lib/readline/callback.c
index 7682cd07..6bb2c3e0 100644
--- a/lib/readline/callback.c
+++ b/lib/readline/callback.c
@@ -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 ();
@@ -102,6 +100,16 @@ rl_callback_handler_install (prompt, linefunc)
_rl_callback_newline ();
}
+#if defined (HANDLE_SIGNALS)
+#define CALLBACK_READ_RETURN() \
+ do { \
+ rl_clear_signals (); \
+ return; \
+ } while (0)
+#else
+#define CALLBACK_READ_RETURN() return
+#endif
+
/* Read one character, and dispatch to the handler if it ends the line. */
void
rl_callback_read_char ()
@@ -117,15 +125,24 @@ rl_callback_read_char ()
}
memcpy ((void *)olevel, (void *)_rl_top_level, sizeof (procenv_t));
+#if defined (HAVE_POSIX_SIGSETJMP)
+ jcode = sigsetjmp (_rl_top_level, 0);
+#else
jcode = setjmp (_rl_top_level);
+#endif
if (jcode)
{
(*rl_redisplay_function) ();
_rl_want_redisplay = 0;
memcpy ((void *)_rl_top_level, (void *)olevel, sizeof (procenv_t));
- return;
+ CALLBACK_READ_RETURN ();
}
+#if defined (HANDLE_SIGNALS)
+ /* Install signal handlers only when readline has control. */
+ rl_set_signals ();
+#endif
+
do
{
RL_CHECK_SIGNALS ();
@@ -135,12 +152,13 @@ rl_callback_read_char ()
if (eof == 0 && (RL_ISSTATE (RL_STATE_ISEARCH) == 0) && RL_ISSTATE (RL_STATE_INPUTPENDING))
rl_callback_read_char ();
- return;
+ CALLBACK_READ_RETURN ();
}
else if (RL_ISSTATE (RL_STATE_NSEARCH))
{
eof = _rl_nsearch_callback (_rl_nscxt);
- return;
+
+ CALLBACK_READ_RETURN ();
}
#if defined (VI_MODE)
else if (RL_ISSTATE (RL_STATE_VIMOTION))
@@ -151,7 +169,7 @@ rl_callback_read_char ()
if (RL_ISSTATE (RL_STATE_NUMERICARG) == 0)
_rl_internal_char_cleanup ();
- return;
+ CALLBACK_READ_RETURN ();
}
#endif
else if (RL_ISSTATE (RL_STATE_NUMERICARG))
@@ -163,7 +181,7 @@ rl_callback_read_char ()
else if (RL_ISSTATE (RL_STATE_NUMERICARG) == 0)
_rl_internal_char_cleanup ();
- return;
+ CALLBACK_READ_RETURN ();
}
else if (RL_ISSTATE (RL_STATE_MULTIKEY))
{
@@ -180,7 +198,7 @@ rl_callback_read_char ()
{
/* 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
+ called when input is available. _rl_callback_data is a
pointer to a struct that has the argument count originally
passed to the registering function and space for any additional
parameters. */
@@ -230,6 +248,8 @@ rl_callback_read_char ()
}
}
while (rl_pending_input || _rl_pushed_input_available () || RL_ISSTATE (RL_STATE_MACROINPUT));
+
+ CALLBACK_READ_RETURN ();
}
/* Remove the handler, and make sure the terminal is in its normal state. */
diff --git a/lib/readline/chardefs.h b/lib/readline/chardefs.h
index e76c34b0..1fa1b089 100644
--- a/lib/readline/chardefs.h
+++ b/lib/readline/chardefs.h
@@ -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
diff --git a/lib/readline/colors.c b/lib/readline/colors.c
new file mode 100644
index 00000000..89d9035f
--- /dev/null
+++ b/lib/readline/colors.c
@@ -0,0 +1,251 @@
+/* `dir', `vdir' and `ls' directory listing programs for GNU.
+
+ Modified by Chet Ramey for Readline.
+
+ Copyright (C) 1985, 1988, 1990-1991, 1995-2010, 2012 Free Software Foundation,
+ Inc.
+
+ 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 3 of the License, 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, see <http://www.gnu.org/licenses/>. */
+
+/* Written by Richard Stallman and David MacKenzie. */
+
+/* Color support by Peter Anvin <Peter.Anvin@linux.org> and Dennis
+ Flaherty <dennisf@denix.elk.miles.com> based on original patches by
+ Greg Lee <lee@uhunix.uhcc.hawaii.edu>. */
+
+#define READLINE_LIBRARY
+
+#if defined (HAVE_CONFIG_H)
+# include <config.h>
+#endif
+
+#include "rlconf.h"
+
+#include <stdio.h>
+
+#include "posixstat.h" // stat related macros (S_ISREG, ...)
+#include <fcntl.h> // S_ISUID
+
+// strlen()
+#if defined (HAVE_STRING_H)
+# include <string.h>
+#else /* !HAVE_STRING_H */
+# include <strings.h>
+#endif /* !HAVE_STRING_H */
+
+// abort()
+#if defined (HAVE_STDLIB_H)
+# include <stdlib.h>
+#else
+# include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+
+#include "readline.h"
+#include "rldefs.h"
+
+#ifdef COLOR_SUPPORT
+
+#include "xmalloc.h"
+#include "colors.h"
+
+static bool is_colored (enum indicator_no type);
+static void restore_default_color (void);
+
+COLOR_EXT_TYPE *_rl_color_ext_list = 0;
+
+/* Output a color indicator (which may contain nulls). */
+void
+_rl_put_indicator (const struct bin_str *ind) {
+ fwrite (ind->string, ind->len, 1, rl_outstream);
+}
+
+static bool
+is_colored (enum indicator_no colored_filetype)
+{
+ size_t len = _rl_color_indicator[colored_filetype].len;
+ char const *s = _rl_color_indicator[colored_filetype].string;
+ return ! (len == 0
+ || (len == 1 && strncmp (s, "0", 1) == 0)
+ || (len == 2 && strncmp (s, "00", 2) == 0));
+}
+
+static void
+restore_default_color (void)
+{
+ _rl_put_indicator (&_rl_color_indicator[C_LEFT]);
+ _rl_put_indicator (&_rl_color_indicator[C_RIGHT]);
+}
+
+void
+_rl_set_normal_color (void)
+{
+ if (is_colored (C_NORM))
+ {
+ _rl_put_indicator (&_rl_color_indicator[C_LEFT]);
+ _rl_put_indicator (&_rl_color_indicator[C_NORM]);
+ _rl_put_indicator (&_rl_color_indicator[C_RIGHT]);
+ }
+}
+
+/* Returns whether any color sequence was printed. */
+bool
+_rl_print_color_indicator (char *f)
+{
+ enum indicator_no colored_filetype;
+ COLOR_EXT_TYPE *ext; /* Color extension */
+ size_t len; /* Length of name */
+
+ const char* name;
+ char *filename;
+ struct stat astat;
+ mode_t mode;
+ int linkok;
+
+ int stat_ok;
+
+ name = f;
+
+ /* This should already have undergone tilde expansion */
+ filename = 0;
+ if (rl_filename_stat_hook)
+ {
+ filename = savestring (f);
+ (*rl_filename_stat_hook) (&filename);
+ name = filename;
+ }
+
+#if defined (HAVE_LSTAT)
+ stat_ok = lstat(name, &astat);
+#else
+ stat_ok = stat(name, &astat);
+#endif
+ if( stat_ok == 0 ) {
+ mode = astat.st_mode;
+ linkok = 1; //f->linkok;
+ }
+ else
+ linkok = -1;
+
+ /* Is this a nonexistent file? If so, linkok == -1. */
+
+ if (linkok == -1 && _rl_color_indicator[C_MISSING].string != NULL)
+ colored_filetype = C_MISSING;
+ else if(stat_ok != 0)
+ {
+ static enum indicator_no filetype_indicator[] = FILETYPE_INDICATORS;
+ colored_filetype = filetype_indicator[normal]; //f->filetype];
+ }
+ else
+ {
+ if (S_ISREG (mode))
+ {
+ colored_filetype = C_FILE;
+
+ if ((mode & S_ISUID) != 0 && is_colored (C_SETUID))
+ colored_filetype = C_SETUID;
+ else if ((mode & S_ISGID) != 0 && is_colored (C_SETGID))
+ colored_filetype = C_SETGID;
+ else if (is_colored (C_CAP) && 0) //f->has_capability)
+ colored_filetype = C_CAP;
+ else if ((mode & S_IXUGO) != 0 && is_colored (C_EXEC))
+ colored_filetype = C_EXEC;
+ else if ((1 < astat.st_nlink) && is_colored (C_MULTIHARDLINK))
+ colored_filetype = C_MULTIHARDLINK;
+ }
+ else if (S_ISDIR (mode))
+ {
+ colored_filetype = C_DIR;
+
+#if defined (S_ISVTX)
+ if ((mode & S_ISVTX) && (mode & S_IWOTH)
+ && is_colored (C_STICKY_OTHER_WRITABLE))
+ colored_filetype = C_STICKY_OTHER_WRITABLE;
+ else
+#endif
+ if ((mode & S_IWOTH) != 0 && is_colored (C_OTHER_WRITABLE))
+ colored_filetype = C_OTHER_WRITABLE;
+#if defined (S_ISVTX)
+ else if ((mode & S_ISVTX) != 0 && is_colored (C_STICKY))
+ colored_filetype = C_STICKY;
+#endif
+ }
+ else if (S_ISLNK (mode))
+ colored_filetype = ((linkok == 0
+ && (!strncmp (_rl_color_indicator[C_LINK].string, "target", 6)
+ || _rl_color_indicator[C_ORPHAN].string))
+ ? C_ORPHAN : C_LINK);
+ else if (S_ISFIFO (mode))
+ colored_filetype = C_FIFO;
+ else if (S_ISSOCK (mode))
+ colored_filetype = C_SOCK;
+ else if (S_ISBLK (mode))
+ colored_filetype = C_BLK;
+ else if (S_ISCHR (mode))
+ colored_filetype = C_CHR;
+ else
+ {
+ /* Classify a file of some other type as C_ORPHAN. */
+ colored_filetype = C_ORPHAN;
+ }
+ }
+
+ /* Check the file's suffix only if still classified as C_FILE. */
+ ext = NULL;
+ if (colored_filetype == C_FILE)
+ {
+ /* Test if NAME has a recognized suffix. */
+ len = strlen (name);
+ name += len; /* Pointer to final \0. */
+ for (ext = _rl_color_ext_list; ext != NULL; ext = ext->next)
+ {
+ if (ext->ext.len <= len
+ && strncmp (name - ext->ext.len, ext->ext.string,
+ ext->ext.len) == 0)
+ break;
+ }
+ }
+
+ free (filename); /* NULL or savestring return value */
+
+ {
+ const struct bin_str *const s
+ = ext ? &(ext->seq) : &_rl_color_indicator[colored_filetype];
+ if (s->string != NULL)
+ {
+ /* Need to reset so not dealing with attribute combinations */
+ if (is_colored (C_NORM))
+ restore_default_color ();
+ _rl_put_indicator (&_rl_color_indicator[C_LEFT]);
+ _rl_put_indicator (s);
+ _rl_put_indicator (&_rl_color_indicator[C_RIGHT]);
+ return 0;
+ }
+ else
+ return 1;
+ }
+}
+
+void
+_rl_prep_non_filename_text (void)
+{
+ if (_rl_color_indicator[C_END].string != NULL)
+ _rl_put_indicator (&_rl_color_indicator[C_END]);
+ else
+ {
+ _rl_put_indicator (&_rl_color_indicator[C_LEFT]);
+ _rl_put_indicator (&_rl_color_indicator[C_RESET]);
+ _rl_put_indicator (&_rl_color_indicator[C_RIGHT]);
+ }
+}
+#endif /* COLOR_SUPPORT */
diff --git a/lib/readline/colors.h b/lib/readline/colors.h
new file mode 100644
index 00000000..fc926e53
--- /dev/null
+++ b/lib/readline/colors.h
@@ -0,0 +1,122 @@
+/* `dir', `vdir' and `ls' directory listing programs for GNU.
+
+ Modified by Chet Ramey for Readline.
+
+ Copyright (C) 1985, 1988, 1990-1991, 1995-2010, 2012 Free Software Foundation,
+ Inc.
+
+ 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 3 of the License, 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, see <http://www.gnu.org/licenses/>. */
+
+/* Written by Richard Stallman and David MacKenzie. */
+
+/* Color support by Peter Anvin <Peter.Anvin@linux.org> and Dennis
+ Flaherty <dennisf@denix.elk.miles.com> based on original patches by
+ Greg Lee <lee@uhunix.uhcc.hawaii.edu>. */
+
+#ifndef _COLORS_H_
+#define _COLORS_H_
+
+#include <stdio.h> // size_t
+
+#if defined(__TANDEM) && defined(HAVE_STDBOOL_H) && (__STDC_VERSION__ < 199901L)
+typedef int _Bool;
+#endif
+
+#if defined (HAVE_STDBOOL_H)
+# include <stdbool.h> // bool
+#else
+typedef int _rl_bool_t;
+
+#ifdef bool
+# undef bool
+#endif
+#define bool _rl_bool_t
+
+#ifndef true
+# define true 1
+# define false 0
+#endif
+
+#endif /* !HAVE_STDBOOL_H */
+
+/* Null is a valid character in a color indicator (think about Epson
+ printers, for example) so we have to use a length/buffer string
+ type. */
+struct bin_str
+ {
+ size_t len;
+ const char *string;
+ };
+
+/* file type indicators (dir, sock, fifo, ...)
+ Default value is initialized in parse-colors.c.
+ It is then modified from the values of $LS_COLORS. */
+extern struct bin_str _rl_color_indicator[];
+
+/* The LS_COLORS variable is in a termcap-like format. */
+typedef struct _color_ext_type
+ {
+ struct bin_str ext; /* The extension we're looking for */
+ struct bin_str seq; /* The sequence to output when we do */
+ struct _color_ext_type *next; /* Next in list */
+ } COLOR_EXT_TYPE;
+
+/* file extensions indicators (.txt, .log, .jpg, ...)
+ Values are taken from $LS_COLORS in rl_parse_colors(). */
+extern COLOR_EXT_TYPE *_rl_color_ext_list;
+
+#define FILETYPE_INDICATORS \
+ { \
+ C_ORPHAN, C_FIFO, C_CHR, C_DIR, C_BLK, C_FILE, \
+ C_LINK, C_SOCK, C_FILE, C_DIR \
+ }
+
+/* Whether we used any colors in the output so far. If so, we will
+ need to restore the default color later. If not, we will need to
+ call prep_non_filename_text before using color for the first time. */
+
+enum indicator_no
+ {
+ C_LEFT, C_RIGHT, C_END, C_RESET, C_NORM, C_FILE, C_DIR, C_LINK,
+ C_FIFO, C_SOCK,
+ C_BLK, C_CHR, C_MISSING, C_ORPHAN, C_EXEC, C_DOOR, C_SETUID, C_SETGID,
+ C_STICKY, C_OTHER_WRITABLE, C_STICKY_OTHER_WRITABLE, C_CAP, C_MULTIHARDLINK,
+ C_CLR_TO_EOL
+ };
+
+
+#if !S_IXUGO
+# define S_IXUGO (S_IXUSR | S_IXGRP | S_IXOTH)
+#endif
+
+enum filetype
+ {
+ unknown,
+ fifo,
+ chardev,
+ directory,
+ blockdev,
+ normal,
+ symbolic_link,
+ sock,
+ whiteout,
+ arg_directory
+ };
+
+extern void _rl_put_indicator (const struct bin_str *ind);
+extern void _rl_set_normal_color (void);
+extern bool _rl_print_color_indicator (char *f);
+extern void _rl_prep_non_filename_text (void);
+
+#endif /* !_COLORS_H_ */
diff --git a/lib/readline/complete.c b/lib/readline/complete.c
index e67cfeb3..cd9aebe8 100644
--- a/lib/readline/complete.c
+++ b/lib/readline/complete.c
@@ -1,6 +1,6 @@
/* complete.c -- filename completion for readline. */
-/* Copyright (C) 1987-2011 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2012 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.
@@ -31,6 +31,8 @@
# include <sys/file.h>
#endif
+#include <signal.h>
+
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif /* HAVE_UNISTD_H */
@@ -64,6 +66,10 @@ extern int errno;
#include "xmalloc.h"
#include "rlprivate.h"
+#if defined (COLOR_SUPPORT)
+# include "colors.h"
+#endif
+
#ifdef __STDC__
typedef int QSFUNC (const void *, const void *);
#else
@@ -94,17 +100,27 @@ extern struct passwd *getpwent PARAMS((void));
longest string in that array. */
rl_compdisp_func_t *rl_completion_display_matches_hook = (rl_compdisp_func_t *)NULL;
-#if defined (VISIBLE_STATS)
+#if defined (VISIBLE_STATS) || defined (COLOR_SUPPORT)
# if !defined (X_OK)
# define X_OK 1
# endif
+#endif
+
+#if defined (VISIBLE_STATS)
static int stat_char PARAMS((char *));
#endif
+#if defined (COLOR_SUPPORT)
+static int colored_stat_start PARAMS((char *));
+static void colored_stat_end PARAMS((void));
+#endif
+
static int path_isdir PARAMS((const char *));
static char *rl_quote_filename PARAMS((char *, int, char *));
+static void _rl_complete_sigcleanup PARAMS((int, void *));
+
static void set_completion_defaults PARAMS((int));
static int get_y_or_n PARAMS((int));
static int _rl_internal_pager PARAMS((int));
@@ -189,6 +205,12 @@ int _rl_completion_columns = -1;
int rl_visible_stats = 0;
#endif /* VISIBLE_STATS */
+#if defined (COLOR_SUPPORT)
+/* Non-zero means to use colors to indicate file type when listing possible
+ completions. The colors used are taken from $LS_COLORS, if set. */
+int _rl_colored_stats = 0;
+#endif
+
/* If non-zero, when completing in the middle of a word, don't insert
characters from the match that match characters following point in
the word. This means, for instance, completing when the cursor is
@@ -206,6 +228,8 @@ rl_icppfunc_t *rl_directory_completion_hook = (rl_icppfunc_t *)NULL;
rl_icppfunc_t *rl_directory_rewrite_hook = (rl_icppfunc_t *)NULL;
+rl_icppfunc_t *rl_filename_stat_hook = (rl_icppfunc_t *)NULL;
+
/* If non-zero, this is the address of a function to call when reading
directory entries from the filesystem for completion and comparing
them to the partial word to be completed. The function should
@@ -457,6 +481,15 @@ _rl_reset_completion_state ()
rl_completion_quote_character = 0;
}
+static void
+_rl_complete_sigcleanup (sig, ptr)
+ int sig;
+ void *ptr;
+{
+ if (sig == SIGINT) /* XXX - for now */
+ _rl_free_match_list ((char **)ptr);
+}
+
/* Set default values for readline word completion. These are the variables
that application completion functions can change or inspect. */
static void
@@ -551,6 +584,8 @@ stat_char (filename)
{
struct stat finfo;
int character, r;
+ char *f;
+ const char *fn;
/* Short-circuit a //server on cygwin, since that will always behave as
a directory. */
@@ -559,10 +594,20 @@ stat_char (filename)
return '/';
#endif
+ f = 0;
+ if (rl_filename_stat_hook)
+ {
+ f = savestring (filename);
+ (*rl_filename_stat_hook) (&f);
+ fn = f;
+ }
+ else
+ fn = filename;
+
#if defined (HAVE_LSTAT) && defined (S_ISLNK)
- r = lstat (filename, &finfo);
+ r = lstat (fn, &finfo);
#else
- r = stat (filename, &finfo);
+ r = stat (fn, &finfo);
#endif
if (r == -1)
@@ -596,10 +641,29 @@ stat_char (filename)
if (access (filename, X_OK) == 0)
character = '*';
}
+
+ free (f);
return (character);
}
#endif /* VISIBLE_STATS */
+#if defined (COLOR_SUPPORT)
+static int
+colored_stat_start (filename)
+ char *filename;
+{
+ _rl_set_normal_color ();
+ return (_rl_print_color_indicator (filename));
+}
+
+static void
+colored_stat_end ()
+{
+ _rl_prep_non_filename_text ();
+ _rl_put_indicator (&_rl_color_indicator[C_CLR_TO_EOL]);
+}
+#endif
+
/* Return the portion of PATHNAME that should be output when listing
possible completions. If we are hacking filename completion, we
are only interested in the basename, the portion following the
@@ -679,7 +743,7 @@ fnwidth (string)
else
{
pos += clen;
- w = wcwidth (wc);
+ w = WCWIDTH (wc);
width += (w >= 0) ? w : 1;
}
#else
@@ -766,7 +830,7 @@ fnprint (to_print, prefix_bytes)
break;
else
{
- w = wcwidth (wc);
+ w = WCWIDTH (wc);
width = (w >= 0) ? w : 1;
}
fwrite (s, 1, tlen, rl_outstream);
@@ -796,13 +860,20 @@ print_filename (to_print, full_pathname, prefix_bytes)
char *s, c, *new_full_pathname, *dn;
extension_char = 0;
- printed_len = fnprint (to_print, prefix_bytes);
+#if defined (COLOR_SUPPORT)
+ /* Defer printing if we want to prefix with a color indicator */
+ if (_rl_colored_stats == 0 || rl_filename_completion_desired == 0)
+#endif
+ printed_len = fnprint (to_print, prefix_bytes);
+ if (rl_filename_completion_desired && (
#if defined (VISIBLE_STATS)
- if (rl_filename_completion_desired && (rl_visible_stats || _rl_complete_mark_directories))
-#else
- if (rl_filename_completion_desired && _rl_complete_mark_directories)
+ rl_visible_stats ||
#endif
+#if defined (COLOR_SUPPORT)
+ _rl_colored_stats ||
+#endif
+ _rl_complete_mark_directories))
{
/* If to_print != full_pathname, to_print is the basename of the
path passed. In this case, we try to expand the directory
@@ -848,8 +919,28 @@ print_filename (to_print, full_pathname, prefix_bytes)
extension_char = stat_char (new_full_pathname);
else
#endif
- if (path_isdir (new_full_pathname))
- extension_char = '/';
+ if (_rl_complete_mark_directories)
+ {
+ dn = 0;
+ if (rl_directory_completion_hook == 0 && rl_filename_stat_hook)
+ {
+ dn = savestring (new_full_pathname);
+ (*rl_filename_stat_hook) (&dn);
+ free (new_full_pathname);
+ new_full_pathname = dn;
+ }
+ if (path_isdir (new_full_pathname))
+ extension_char = '/';
+ }
+
+#if defined (COLOR_SUPPORT)
+ if (_rl_colored_stats)
+ {
+ colored_stat_start (new_full_pathname);
+ printed_len = fnprint (to_print, prefix_bytes);
+ colored_stat_end ();
+ }
+#endif
xfree (new_full_pathname);
to_print[-1] = c;
@@ -862,8 +953,18 @@ print_filename (to_print, full_pathname, prefix_bytes)
extension_char = stat_char (s);
else
#endif
- if (path_isdir (s))
+ if (_rl_complete_mark_directories && path_isdir (s))
extension_char = '/';
+
+#if defined (COLOR_SUPPORT)
+ if (_rl_colored_stats)
+ {
+ colored_stat_start (s);
+ printed_len = fnprint (to_print, prefix_bytes);
+ colored_stat_end ();
+ }
+#endif
+
}
xfree (s);
@@ -1058,10 +1159,13 @@ gen_completion_matches (text, start, end, our_func, found_quote, quote_char)
variable rl_attempted_completion_function. */
if (rl_attempted_completion_function)
{
- _rl_interrupt_immediately++;
matches = (*rl_attempted_completion_function) (text, start, end);
- if (_rl_interrupt_immediately > 0)
- _rl_interrupt_immediately--;
+ if (RL_SIG_RECEIVED())
+ {
+ _rl_free_match_list (matches);
+ matches = 0;
+ RL_CHECK_SIGNALS ();
+ }
if (matches || rl_attempted_completion_over)
{
@@ -1072,7 +1176,15 @@ gen_completion_matches (text, start, end, our_func, found_quote, quote_char)
/* XXX -- filename dequoting moved into rl_filename_completion_function */
+ /* rl_completion_matches will check for signals as well to avoid a long
+ delay while reading a directory. */
matches = rl_completion_matches (text, our_func);
+ if (RL_SIG_RECEIVED())
+ {
+ _rl_free_match_list (matches);
+ matches = 0;
+ RL_CHECK_SIGNALS ();
+ }
return matches;
}
@@ -1147,9 +1259,11 @@ compute_lcd_of_matches (match_list, matches, text)
{
register int i, c1, c2, si;
int low; /* Count of max-matched characters. */
+ int lx;
char *dtext; /* dequoted TEXT, if needed */
#if defined (HANDLE_MULTIBYTE)
int v;
+ size_t v1, v2;
mbstate_t ps1, ps2;
wchar_t wc1, wc2;
#endif
@@ -1182,14 +1296,20 @@ compute_lcd_of_matches (match_list, matches, text)
#if defined (HANDLE_MULTIBYTE)
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
{
- v = mbrtowc (&wc1, match_list[i]+si, strlen (match_list[i]+si), &ps1);
- mbrtowc (&wc2, match_list[i+1]+si, strlen (match_list[i+1]+si), &ps2);
+ v1 = mbrtowc(&wc1, match_list[i]+si, strlen (match_list[i]+si), &ps1);
+ v2 = mbrtowc (&wc2, match_list[i+1]+si, strlen (match_list[i+1]+si), &ps2);
+ if (MB_INVALIDCH (v1) || MB_INVALIDCH (v2))
+ {
+ if (c1 != c2) /* do byte comparison */
+ break;
+ continue;
+ }
wc1 = towlower (wc1);
wc2 = towlower (wc2);
if (wc1 != wc2)
break;
- else if (v > 1)
- si += v - 1;
+ else if (v1 > 1)
+ si += v1 - 1;
}
else
#endif
@@ -1264,21 +1384,20 @@ compute_lcd_of_matches (match_list, matches, text)
qsort (match_list+1, matches, sizeof(char *), (QSFUNC *)_rl_qsort_string_compare);
si = strlen (text);
- if (si <= low)
- {
- for (i = 1; i <= matches; i++)
- if (strncmp (match_list[i], text, si) == 0)
- {
- strncpy (match_list[0], match_list[i], low);
- break;
- }
- /* no casematch, use first entry */
- if (i > matches)
- strncpy (match_list[0], match_list[1], low);
- }
- else
- /* otherwise, just use the text the user typed. */
- strncpy (match_list[0], text, low);
+ lx = (si <= low) ? si : low; /* check shorter of text and matches */
+ /* Try to preserve the case of what the user typed in the presence of
+ multiple matches: check each match for something that matches
+ what the user typed taking case into account; use it up to common
+ length of matches if one is found. If not, just use first match. */
+ for (i = 1; i <= matches; i++)
+ if (strncmp (match_list[i], text, lx) == 0)
+ {
+ strncpy (match_list[0], match_list[i], low);
+ break;
+ }
+ /* no casematch, use first entry */
+ if (i > matches)
+ strncpy (match_list[0], match_list[1], low);
FREE (dtext);
}
@@ -1305,7 +1424,7 @@ postprocess_matches (matchesp, matching_filenames)
return 0;
/* It seems to me that in all the cases we handle we would like
- to ignore duplicate possiblilities. Scan for the text to
+ to ignore duplicate possibilities. Scan for the text to
insert being identical to the other completions. */
if (rl_ignore_completion_duplicates)
{
@@ -1463,7 +1582,7 @@ rl_display_match_list (matches, len, max)
/* Have we reached the end of this line? */
if (matches[i+1])
{
- if (i && (limit > 1) && (i % limit) == 0)
+ if (limit == 1 || (i && (limit > 1) && (i % limit) == 0))
{
rl_crlf ();
lines++;
@@ -1672,7 +1791,7 @@ append_to_match (text, delimiter, quote_char, nontrivial_match)
char *text;
int delimiter, quote_char, nontrivial_match;
{
- char temp_string[4], *filename;
+ char temp_string[4], *filename, *fn;
int temp_string_index, s;
struct stat finfo;
@@ -1691,6 +1810,13 @@ append_to_match (text, delimiter, quote_char, nontrivial_match)
if (rl_filename_completion_desired)
{
filename = tilde_expand (text);
+ if (rl_filename_stat_hook)
+ {
+ fn = savestring (filename);
+ (*rl_filename_stat_hook) (&fn);
+ xfree (filename);
+ filename = fn;
+ }
s = (nontrivial_match && rl_completion_mark_symlink_dirs == 0)
? LSTAT (filename, &finfo)
: stat (filename, &finfo);
@@ -1710,8 +1836,7 @@ append_to_match (text, delimiter, quote_char, nontrivial_match)
#ifdef S_ISLNK
/* Don't add anything if the filename is a symlink and resolves to a
directory. */
- else if (s == 0 && S_ISLNK (finfo.st_mode) &&
- stat (filename, &finfo) == 0 && S_ISDIR (finfo.st_mode))
+ else if (s == 0 && S_ISLNK (finfo.st_mode) && path_isdir (filename))
;
#endif
else
@@ -1831,10 +1956,8 @@ rl_complete_internal (what_to_do)
/* nontrivial_lcd is set if the common prefix adds something to the word
being completed. */
nontrivial_lcd = matches && strcmp (text, matches[0]) != 0;
-#if 1
if (what_to_do == '!' || what_to_do == '@')
tlen = strlen (text);
-#endif
xfree (text);
if (matches == 0)
@@ -1868,10 +1991,6 @@ rl_complete_internal (what_to_do)
case '!':
case '@':
/* Insert the first match with proper quoting. */
-#if 0
- if (*matches[0])
- insert_match (matches[0], start, matches[1] ? MULT_MATCH : SINGLE_MATCH, &quote_char);
-#else
if (what_to_do == TAB)
{
if (*matches[0])
@@ -1886,7 +2005,6 @@ rl_complete_internal (what_to_do)
if (mlen >= tlen)
insert_match (matches[0], start, matches[1] ? MULT_MATCH : SINGLE_MATCH, &quote_char);
}
-#endif
/* If there are more matches, ring the bell to indicate.
If we are in vi mode, Posix.2 says to not ring the bell.
@@ -1922,7 +2040,14 @@ rl_complete_internal (what_to_do)
break;
case '?':
+ if (rl_completion_display_matches_hook == 0)
+ {
+ _rl_sigcleanup = _rl_complete_sigcleanup;
+ _rl_sigcleanarg = matches;
+ }
display_matches (matches);
+ _rl_sigcleanup = 0;
+ _rl_sigcleanarg = 0;
break;
default:
@@ -1930,6 +2055,7 @@ rl_complete_internal (what_to_do)
rl_ding ();
FREE (saved_line_buffer);
RL_UNSETSTATE(RL_STATE_COMPLETING);
+ _rl_free_match_list (matches);
_rl_reset_completion_state ();
return 1;
}
@@ -1971,6 +2097,8 @@ rl_completion_matches (text, entry_function)
const char *text;
rl_compentry_func_t *entry_function;
{
+ register int i;
+
/* Number of slots in match_list. */
int match_list_size;
@@ -1988,18 +2116,36 @@ rl_completion_matches (text, entry_function)
match_list = (char **)xmalloc ((match_list_size + 1) * sizeof (char *));
match_list[1] = (char *)NULL;
- _rl_interrupt_immediately++;
while (string = (*entry_function) (text, matches))
{
- if (matches + 1 == match_list_size)
+ if (RL_SIG_RECEIVED ())
+ {
+ /* Start at 1 because we don't set matches[0] in this function.
+ Only free the list members if we're building match list from
+ rl_filename_completion_function, since we know that doesn't
+ free the strings it returns. */
+ if (entry_function == rl_filename_completion_function)
+ {
+ for (i = 1; match_list[i]; i++)
+ xfree (match_list[i]);
+ }
+ xfree (match_list);
+ match_list = 0;
+ match_list_size = 0;
+ matches = 0;
+ RL_CHECK_SIGNALS ();
+ }
+
+ if (matches + 1 >= match_list_size)
match_list = (char **)xrealloc
(match_list, ((match_list_size += 10) + 1) * sizeof (char *));
+ if (match_list == 0)
+ return (match_list);
+
match_list[++matches] = string;
match_list[matches + 1] = (char *)NULL;
}
- if (_rl_interrupt_immediately > 0)
- _rl_interrupt_immediately--;
/* If there were any matches, then look through them finding out the
lowest common denominator. That then becomes match_list[0]. */
@@ -2038,7 +2184,9 @@ rl_username_completion_function (text, state)
username = savestring (&text[first_char_loc]);
namelen = strlen (username);
+#if defined (HAVE_GETPWENT)
setpwent ();
+#endif
}
#if defined (HAVE_GETPWENT)
@@ -2075,8 +2223,9 @@ rl_username_completion_function (text, state)
/* Return non-zero if CONVFN matches FILENAME up to the length of FILENAME
(FILENAME_LEN). If _rl_completion_case_fold is set, compare without
- regard to the alphabetic case of characters. CONVFN is the possibly-
- converted directory entry; FILENAME is what the user typed. */
+ regard to the alphabetic case of characters. If
+ _rl_completion_case_map is set, make `-' and `_' equivalent. CONVFN is
+ the possibly-converted directory entry; FILENAME is what the user typed. */
static int
complete_fncmp (convfn, convlen, filename, filename_len)
const char *convfn;
@@ -2086,34 +2235,110 @@ complete_fncmp (convfn, convlen, filename, filename_len)
{
register char *s1, *s2;
int d, len;
+#if defined (HANDLE_MULTIBYTE)
+ size_t v1, v2;
+ mbstate_t ps1, ps2;
+ wchar_t wc1, wc2;
+#endif
+
+#if defined (HANDLE_MULTIBYTE)
+ memset (&ps1, 0, sizeof (mbstate_t));
+ memset (&ps2, 0, sizeof (mbstate_t));
+#endif
+
+ if (filename_len == 0)
+ return 1;
+ if (convlen < filename_len)
+ return 0;
+
+ len = filename_len;
+ s1 = (char *)convfn;
+ s2 = (char *)filename;
/* Otherwise, if these match up to the length of filename, then
it is a match. */
if (_rl_completion_case_fold && _rl_completion_case_map)
{
/* Case-insensitive comparison treating _ and - as equivalent */
- if (filename_len == 0)
- return 1;
- if (convlen < filename_len)
- return 0;
- s1 = (char *)convfn;
- s2 = (char *)filename;
- len = filename_len;
- do
+#if defined (HANDLE_MULTIBYTE)
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ {
+ do
+ {
+ v1 = mbrtowc (&wc1, s1, convlen, &ps1);
+ v2 = mbrtowc (&wc2, s2, filename_len, &ps2);
+ if (v1 == 0 && v2 == 0)
+ return 1;
+ else if (MB_INVALIDCH (v1) || MB_INVALIDCH (v2))
+ {
+ if (*s1 != *s2) /* do byte comparison */
+ return 0;
+ else if ((*s1 == '-' || *s1 == '_') && (*s2 == '-' || *s2 == '_'))
+ return 0;
+ s1++; s2++; len--;
+ continue;
+ }
+ wc1 = towlower (wc1);
+ wc2 = towlower (wc2);
+ s1 += v1;
+ s2 += v1;
+ len -= v1;
+ if ((wc1 == L'-' || wc1 == L'_') && (wc2 == L'-' || wc2 == L'_'))
+ continue;
+ if (wc1 != wc2)
+ return 0;
+ }
+ while (len != 0);
+ }
+ else
+#endif
{
- d = _rl_to_lower (*s1) - _rl_to_lower (*s2);
- /* *s1 == [-_] && *s2 == [-_] */
- if ((*s1 == '-' || *s1 == '_') && (*s2 == '-' || *s2 == '_'))
- d = 0;
- if (d != 0)
- return 0;
- s1++; s2++; /* already checked convlen >= filename_len */
+ do
+ {
+ d = _rl_to_lower (*s1) - _rl_to_lower (*s2);
+ /* *s1 == [-_] && *s2 == [-_] */
+ if ((*s1 == '-' || *s1 == '_') && (*s2 == '-' || *s2 == '_'))
+ d = 0;
+ if (d != 0)
+ return 0;
+ s1++; s2++; /* already checked convlen >= filename_len */
+ }
+ while (--len != 0);
}
- while (--len != 0);
+
return 1;
}
else if (_rl_completion_case_fold)
{
+#if defined (HANDLE_MULTIBYTE)
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ {
+ do
+ {
+ v1 = mbrtowc (&wc1, s1, convlen, &ps1);
+ v2 = mbrtowc (&wc2, s2, filename_len, &ps2);
+ if (v1 == 0 && v2 == 0)
+ return 1;
+ else if (MB_INVALIDCH (v1) || MB_INVALIDCH (v2))
+ {
+ if (*s1 != *s2) /* do byte comparison */
+ return 0;
+ s1++; s2++; len--;
+ continue;
+ }
+ wc1 = towlower (wc1);
+ wc2 = towlower (wc2);
+ if (wc1 != wc2)
+ return 0;
+ s1 += v1;
+ s2 += v1;
+ len -= v1;
+ }
+ while (len != 0);
+ return 1;
+ }
+ else
+#endif
if ((_rl_to_lower (convfn[0]) == _rl_to_lower (filename[0])) &&
(convlen >= filename_len) &&
(_rl_strnicmp (filename, convfn, filename_len) == 0))
@@ -2233,8 +2458,9 @@ rl_filename_completion_function (text, state)
}
directory = opendir (dirname);
- /* Now dequote a non-null filename. */
- if (filename && *filename && rl_completion_found_quote && rl_filename_dequoting_function)
+ /* Now dequote a non-null filename. FILENAME will not be NULL, but may
+ be empty. */
+ if (*filename && rl_completion_found_quote && rl_filename_dequoting_function)
{
/* delete single and double quotes */
temp = (*rl_filename_dequoting_function) (filename, rl_completion_quote_character);
@@ -2598,6 +2824,11 @@ rl_menu_complete (count, ignore)
full_completion = 1;
return (0);
}
+ else if (_rl_menu_complete_prefix_first)
+ {
+ rl_ding ();
+ return (0);
+ }
}
else if (match_list_size <= 1)
{
diff --git a/lib/readline/display.c b/lib/readline/display.c
index e4105ee8..913e0da0 100644
--- a/lib/readline/display.c
+++ b/lib/readline/display.c
@@ -1,6 +1,6 @@
/* display.c -- readline redisplay facility. */
-/* Copyright (C) 1987-2009 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2013 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.
@@ -41,6 +41,10 @@
#include <stdio.h>
+#ifdef __MSDOS__
+# include <pc.h>
+#endif
+
/* System-specific feature definitions and include files. */
#include "rldefs.h"
#include "rlmbutil.h"
@@ -63,6 +67,7 @@ static void update_line PARAMS((char *, char *, int, int, int, int));
static void space_to_eol PARAMS((int));
static void delete_chars PARAMS((int));
static void insert_some_chars PARAMS((char *, int, int));
+static void open_some_spaces PARAMS((int));
static void cr PARAMS((void));
/* State of visible and invisible lines. */
@@ -165,6 +170,7 @@ int _rl_last_v_pos = 0;
static int cpos_adjusted;
static int cpos_buffer_position;
+static int displaying_prompt_first_line;
static int prompt_multibyte_chars;
/* Number of lines currently on screen minus 1. */
@@ -176,7 +182,8 @@ int _rl_vis_botlin = 0;
static int last_lmargin;
/* A buffer for `modeline' messages. */
-static char msg_buf[128];
+static char *msg_buf = 0;
+static int msg_bufsiz = 0;
/* Non-zero forces the redisplay even if we thought it was unnecessary. */
static int forced_display;
@@ -232,6 +239,18 @@ static int saved_local_length;
static int saved_invis_chars_first_line;
static int saved_physical_chars;
+/* Return a character indicating the editing mode, for use in the prompt. */
+static int
+prompt_modechar ()
+{
+ if (rl_editing_mode == emacs_mode)
+ return '@';
+ else if (_rl_keymap == vi_insertion_keymap)
+ return '+'; /* vi insert mode */
+ else
+ return ':'; /* vi command mode */
+}
+
/* Expand the prompt string S and return the number of visible
characters in *LP, if LP is not null. This is currently more-or-less
a placeholder for expansion. LIP, if non-null is a place to store the
@@ -258,7 +277,16 @@ expand_prompt (pmt, lp, lip, niflp, vlp)
/* Short-circuit if we can. */
if ((MB_CUR_MAX <= 1 || rl_byte_oriented) && strchr (pmt, RL_PROMPT_START_IGNORE) == 0)
{
- r = savestring (pmt);
+ if (pmt == rl_prompt && _rl_show_mode_in_prompt)
+ {
+ l = strlen (pmt);
+ r = (char *)xmalloc (l + 2);
+ r[0] = prompt_modechar ();
+ strcpy (r + 1, pmt);
+ }
+ else
+ r = savestring (pmt);
+
if (lp)
*lp = strlen (r);
if (lip)
@@ -271,13 +299,20 @@ expand_prompt (pmt, lp, lip, niflp, vlp)
}
l = strlen (pmt);
- r = ret = (char *)xmalloc (l + 1);
+ r = ret = (char *)xmalloc (l + 2);
+
+ rl = physchars = 0; /* move up here so mode show can set them */
+ if (pmt == rl_prompt && _rl_show_mode_in_prompt)
+ {
+ *r++ = prompt_modechar ();
+ rl = physchars = 1;
+ }
invfl = 0; /* invisible chars in first line of prompt */
invflset = 0; /* we only want to set invfl once */
igstart = 0;
- for (rl = ignoring = last = ninvis = physchars = 0, p = pmt; p && *p; p++)
+ for (ignoring = last = ninvis = 0, p = pmt; p && *p; p++)
{
/* This code strips the invisible character string markers
RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE */
@@ -366,6 +401,12 @@ _rl_strip_prompt (pmt)
return ret;
}
+void
+_rl_reset_prompt ()
+{
+ rl_visible_prompt_length = rl_expand_prompt (rl_prompt);
+}
+
/*
* Expand the prompt string into the various display components, if
* necessary.
@@ -707,10 +748,9 @@ rl_redisplay ()
/* Now account for invisible characters in the current line. */
/* XXX - this assumes that the invisible characters may be split, but only
between the first and the last lines. */
- temp += ((local_prompt_prefix == 0) ? ((newlines == 0) ? prompt_invis_chars_first_line
- : ((newlines == prompt_lines_estimate) ? wrap_offset : prompt_invis_chars_first_line))
- : ((newlines == 0) ? wrap_offset : 0));
-
+ temp += (newlines == 0) ? prompt_invis_chars_first_line
+ : ((newlines == prompt_lines_estimate) ? wrap_offset : prompt_invis_chars_first_line);
+
inv_lbreaks[++newlines] = temp;
#if defined (HANDLE_MULTIBYTE)
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0 && prompt_multibyte_chars > 0)
@@ -761,7 +801,7 @@ rl_redisplay ()
break; /* Found '\0' */
else
{
- temp = wcwidth (wc);
+ temp = WCWIDTH (wc);
wc_width = (temp >= 0) ? temp : 1;
}
}
@@ -925,7 +965,7 @@ rl_redisplay ()
/* If we can move the cursor up and down, then use multiple lines,
otherwise, let long lines display in a single terminal line, and
horizontally scroll it. */
-
+ displaying_prompt_first_line = 1;
if (_rl_horizontal_scroll_mode == 0 && _rl_term_up && *_rl_term_up)
{
int nleft, pos, changed_screen_line, tx;
@@ -1179,6 +1219,8 @@ rl_redisplay ()
else
lmargin = last_lmargin;
+ displaying_prompt_first_line = lmargin < nleft;
+
/* If the first character on the screen isn't the first character
in the display line, indicate this with a special character. */
if (lmargin > 0)
@@ -1204,7 +1246,8 @@ rl_redisplay ()
_rl_screenwidth + (lmargin ? 0 : wrap_offset),
0);
- if ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) && OLD_CPOS_IN_PROMPT())
+ if ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) &&
+ displaying_prompt_first_line && OLD_CPOS_IN_PROMPT())
_rl_last_c_pos -= prompt_invis_chars_first_line; /* XXX - was wrap_offset */
/* If the visible new line is shorter than the old, but the number
@@ -1212,7 +1255,7 @@ rl_redisplay ()
the new line, we need to clear to eol. */
t = _rl_last_c_pos - M_OFFSET (lmargin, wrap_offset);
if ((M_OFFSET (lmargin, wrap_offset) > visible_wrap_offset) &&
- (_rl_last_c_pos == out) &&
+ (_rl_last_c_pos == out) && displaying_prompt_first_line &&
t < visible_first_line_len)
{
nleft = _rl_screenwidth - t;
@@ -1274,6 +1317,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
int temp, lendiff, wsatend, od, nd, twidth, o_cpos;
int current_invis_chars;
int col_lendiff, col_temp;
+ int bytes_to_insert;
#if defined (HANDLE_MULTIBYTE)
mbstate_t ps_new, ps_old;
int new_offset, old_offset;
@@ -1300,7 +1344,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
size_t ret;
/* This fixes only double-column characters, but if the wrapped
- character comsumes more than three columns, spaces will be
+ character consumes more than three columns, spaces will be
inserted in the string buffer. */
if (current_line < line_state_visible->wbsize && line_state_visible->wrapped_line[current_line] > 0)
_rl_clear_to_eol (line_state_visible->wrapped_line[current_line]);
@@ -1315,7 +1359,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
else if (MB_NULLWCH (ret))
tempwidth = 0;
else
- tempwidth = wcwidth (wc);
+ tempwidth = WCWIDTH (wc);
if (tempwidth > 0)
{
@@ -1335,7 +1379,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
memcpy (old, new, bytes);
/* Fix up indices if we copy data from one line to another */
omax += bytes - ret;
- for (i = current_line+1; i < inv_botlin+1; i++)
+ for (i = current_line+1; i <= inv_botlin+1; i++)
vis_lbreaks[i] += bytes - ret;
}
}
@@ -1372,6 +1416,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
temp = (omax < nmax) ? omax : nmax;
if (memcmp (old, new, temp) == 0) /* adding at the end */
{
+ new_offset = old_offset = temp;
ofd = old + temp;
nfd = new + temp;
}
@@ -1382,6 +1427,8 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
if (omax == nmax && STREQN (new, old, omax))
{
+ old_offset = omax;
+ new_offset = nmax;
ofd = old + omax;
nfd = new + nmax;
}
@@ -1394,6 +1441,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
{
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;
}
@@ -1417,6 +1465,27 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
if (ofd == oe && nfd == ne)
return;
+#if defined (HANDLE_MULTIBYTE)
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0 && _rl_utf8locale)
+ {
+ wchar_t wc;
+ mbstate_t ps = { 0 };
+ int t;
+
+ /* If the first character in the difference is a zero-width character,
+ assume it's a combining character and back one up so the two base
+ characters no longer compare equivalently. */
+ t = mbrtowc (&wc, ofd, MB_CUR_MAX, &ps);
+ if (t > 0 && UNICODE_COMBINING_CHAR (wc) && WCWIDTH (wc) == 0)
+ {
+ old_offset = _rl_find_prev_mbchar (old, ofd - old, MB_FIND_ANY);
+ new_offset = _rl_find_prev_mbchar (new, nfd - new, MB_FIND_ANY);
+ ofd = old + old_offset; /* equal by definition */
+ nfd = new + new_offset;
+ }
+ }
+#endif
+
wsatend = 1; /* flag for trailing whitespace */
#if defined (HANDLE_MULTIBYTE)
@@ -1424,6 +1493,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
{
ols = old + _rl_find_prev_mbchar (old, oe - old, MB_FIND_ANY);
nls = new + _rl_find_prev_mbchar (new, ne - new, MB_FIND_ANY);
+
while ((ols > ofd) && (nls > nfd))
{
memset (&ps_old, 0, sizeof (mbstate_t));
@@ -1540,10 +1610,10 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
o_cpos = _rl_last_c_pos;
/* When this function returns, _rl_last_c_pos is correct, and an absolute
- cursor postion in multibyte mode, but a buffer index when not in a
+ cursor position in multibyte mode, but a buffer index when not in a
multibyte locale. */
_rl_move_cursor_relative (od, old);
-#if 1
+
#if defined (HANDLE_MULTIBYTE)
/* We need to indicate that the cursor position is correct in the presence of
invisible characters in the prompt string. Let's see if setting this when
@@ -1553,11 +1623,10 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
_rl_last_c_pos == prompt_physical_chars)
cpos_adjusted = 1;
#endif
-#endif
/* if (len (new) > len (old))
- lendiff == difference in buffer
- col_lendiff == difference on screen
+ lendiff == difference in buffer (bytes)
+ col_lendiff == difference on screen (columns)
When not using multibyte characters, these are equal */
lendiff = (nls - nfd) - (ols - ofd);
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
@@ -1583,6 +1652,10 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
}
}
+ /* We use temp as a count of the number of bytes from the first difference
+ to the end of the new line. col_temp is the corresponding number of
+ screen columns. A `dumb' update moves to the spot of first difference
+ and writes TEMP bytes. */
/* Insert (diff (len (old), len (new)) ch. */
temp = ne - nfd;
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
@@ -1590,6 +1663,10 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
else
col_temp = temp;
+ /* how many bytes from the new line buffer to write to the display */
+ bytes_to_insert = nls - nfd;
+
+ /* col_lendiff > 0 if we are adding characters to the line */
if (col_lendiff > 0) /* XXX - was lendiff */
{
/* Non-zero if we're increasing the number of lines. */
@@ -1603,11 +1680,11 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
if (lendiff < 0)
{
_rl_output_some_chars (nfd, temp);
- _rl_last_c_pos += _rl_col_width (nfd, 0, temp, 1);
+ _rl_last_c_pos += col_temp; /* XXX - was _rl_col_width (nfd, 0, temp, 1); */
/* If nfd begins before any invisible characters in the prompt,
adjust _rl_last_c_pos to account for wrap_offset and set
cpos_adjusted to let the caller know. */
- if (current_line == 0 && wrap_offset && ((nfd - new) <= prompt_last_invisible))
+ if (current_line == 0 && displaying_prompt_first_line && wrap_offset && ((nfd - new) <= prompt_last_invisible))
{
_rl_last_c_pos -= wrap_offset;
cpos_adjusted = 1;
@@ -1638,57 +1715,42 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
(col_lendiff < prompt_visible_length)) == 0) &&
(visible_wrap_offset >= current_invis_chars))
{
- insert_some_chars (nfd, lendiff, col_lendiff);
- _rl_last_c_pos += col_lendiff;
- }
-#if 0 /* XXX - for now */
- else if ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) && _rl_last_c_pos == 0 && wrap_offset && (nfd-new) <= prompt_last_invisible && col_lendiff < prompt_visible_length && visible_wrap_offset >= current_invis_chars)
- {
- _rl_output_some_chars (nfd, lendiff);
- _rl_last_c_pos += col_lendiff;
+ open_some_spaces (col_lendiff);
+ _rl_output_some_chars (nfd, bytes_to_insert);
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ _rl_last_c_pos += _rl_col_width (nfd, 0, bytes_to_insert, 1);
+ else
+ _rl_last_c_pos += bytes_to_insert;
}
-#endif
else if ((MB_CUR_MAX == 1 || rl_byte_oriented != 0) && *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. */
- /* However, this screws up the rest of this block, which
- assumes you've done the insert because you can. */
- _rl_output_some_chars (nfd, lendiff);
- _rl_last_c_pos += col_lendiff;
+ _rl_output_some_chars (nfd, temp);
+ _rl_last_c_pos += col_temp;
+ return;
}
- else
+ else /* just write from first difference to end of new line */
{
_rl_output_some_chars (nfd, temp);
_rl_last_c_pos += col_temp;
/* If nfd begins before the last invisible character in the
prompt, adjust _rl_last_c_pos to account for wrap_offset
and set cpos_adjusted to let the caller know. */
- if ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) && current_line == 0 && wrap_offset && ((nfd - new) <= prompt_last_invisible))
+ if ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) && current_line == 0 && displaying_prompt_first_line && wrap_offset && ((nfd - new) <= prompt_last_invisible))
{
_rl_last_c_pos -= wrap_offset;
cpos_adjusted = 1;
}
return;
}
- /* Copy (new) chars to screen from first diff to last match. */
- temp = nls - nfd;
- if ((temp - lendiff) > 0)
+
+ if (bytes_to_insert > lendiff)
{
- _rl_output_some_chars (nfd + lendiff, temp - lendiff);
- /* XXX -- this bears closer inspection. Fixes a redisplay bug
- reported against bash-3.0-alpha by Andreas Schwab involving
- multibyte characters and prompt strings with invisible
- characters, but was previously disabled. */
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- twidth = _rl_col_width (nfd+lendiff, 0, temp-col_lendiff, 1);
- else
- twidth = temp - lendiff;
- _rl_last_c_pos += twidth;
/* If nfd begins before the last invisible character in the
prompt, adjust _rl_last_c_pos to account for wrap_offset
and set cpos_adjusted to let the caller know. */
- if ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) && current_line == 0 && wrap_offset && ((nfd - new) <= prompt_last_invisible))
+ if ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) && current_line == 0 && displaying_prompt_first_line && wrap_offset && ((nfd - new) <= prompt_last_invisible))
{
_rl_last_c_pos -= wrap_offset;
cpos_adjusted = 1;
@@ -1706,6 +1768,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
a physical character position. */
if ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) &&
current_line == prompt_last_screen_line && wrap_offset &&
+ displaying_prompt_first_line &&
wrap_offset != prompt_invis_chars_first_line &&
((nfd-new) < (prompt_last_invisible-(current_line*_rl_screenwidth))))
{
@@ -1723,32 +1786,47 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
prompt string, don't bother. It screws up the assumptions
about what's on the screen. */
if (_rl_horizontal_scroll_mode && _rl_last_c_pos == 0 &&
+ displaying_prompt_first_line &&
-lendiff == visible_wrap_offset)
col_lendiff = 0;
+ /* If we have moved lmargin and we're shrinking the line, we've
+ already moved the cursor to the first character of the new line,
+ so deleting -col_lendiff characters will mess up the cursor
+ position calculation */
+ if (_rl_horizontal_scroll_mode && displaying_prompt_first_line == 0 &&
+ col_lendiff && _rl_last_c_pos < -col_lendiff)
+ col_lendiff = 0;
+
if (col_lendiff)
delete_chars (-col_lendiff); /* delete (diff) characters */
- /* Copy (new) chars to screen from first diff to last match */
- temp = nls - nfd;
- if (temp > 0)
+ /* Copy (new) chars to screen from first diff to last match,
+ overwriting what is there. */
+ if (bytes_to_insert > 0)
{
/* If nfd begins at the prompt, or before the invisible
characters in the prompt, we need to adjust _rl_last_c_pos
in a multibyte locale to account for the wrap offset and
set cpos_adjusted accordingly. */
- _rl_output_some_chars (nfd, temp);
+ _rl_output_some_chars (nfd, bytes_to_insert);
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
{
- _rl_last_c_pos += _rl_col_width (nfd, 0, temp, 1);
- if (current_line == 0 && wrap_offset && ((nfd - new) <= prompt_last_invisible))
+ _rl_last_c_pos += _rl_col_width (nfd, 0, bytes_to_insert, 1);
+ if (current_line == 0 && wrap_offset &&
+ displaying_prompt_first_line &&
+ _rl_last_c_pos > wrap_offset &&
+ ((nfd - new) <= prompt_last_invisible))
{
_rl_last_c_pos -= wrap_offset;
cpos_adjusted = 1;
}
}
else
- _rl_last_c_pos += temp;
+ _rl_last_c_pos += bytes_to_insert;
+
+ if (_rl_horizontal_scroll_mode && ((oe-old) > (ne-new)))
+ goto clear_rest_of_line;
}
}
/* Otherwise, print over the existing material. */
@@ -1764,29 +1842,29 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
_rl_last_c_pos += col_temp; /* XXX */
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
{
- if (current_line == 0 && wrap_offset && ((nfd - new) <= prompt_last_invisible))
+ if (current_line == 0 && wrap_offset &&
+ displaying_prompt_first_line &&
+ _rl_last_c_pos > wrap_offset &&
+ ((nfd - new) <= prompt_last_invisible))
{
_rl_last_c_pos -= wrap_offset;
cpos_adjusted = 1;
}
}
}
+clear_rest_of_line:
lendiff = (oe - old) - (ne - new);
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
col_lendiff = _rl_col_width (old, 0, oe - old, 1) - _rl_col_width (new, 0, ne - new, 1);
else
col_lendiff = lendiff;
-#if 0
- if (col_lendiff)
-#else
/* If we've already printed over the entire width of the screen,
including the old material, then col_lendiff doesn't matter and
space_to_eol will insert too many spaces. XXX - maybe we should
adjust col_lendiff based on the difference between _rl_last_c_pos
and _rl_screenwidth */
if (col_lendiff && ((MB_CUR_MAX == 1 || rl_byte_oriented) || (_rl_last_c_pos < _rl_screenwidth)))
-#endif
{
if (_rl_term_autowrap && current_line < inv_botlin)
space_to_eol (col_lendiff);
@@ -1938,6 +2016,9 @@ _rl_move_cursor_relative (new, data)
else
dpos = _rl_col_width (data, 0, new, 1);
+ if (displaying_prompt_first_line == 0)
+ adjust = 0;
+
/* Use NEW when comparing against the last invisible character in the
prompt string, since they're both buffer indices and DPOS is a
desired display position. */
@@ -2056,9 +2137,18 @@ _rl_move_vert (to)
}
else
{ /* delta < 0 */
+#ifdef __DJGPP__
+ int row, col;
+
+ fflush (rl_outstream);
+ ScreenGetCursor (&row, &col);
+ ScreenSetCursor (row + delta, col);
+ i = -delta;
+#else
if (_rl_term_up && *_rl_term_up)
for (i = 0; i < -delta; i++)
tputs (_rl_term_up, 1, _rl_output_character_function);
+#endif /* !__DJGPP__ */
}
_rl_last_v_pos = to; /* Now TO is here */
@@ -2136,6 +2226,9 @@ rl_message (va_alist)
#if defined (PREFER_VARARGS)
char *format;
#endif
+#if defined (HAVE_VSNPRINTF)
+ int bneed;
+#endif
#if defined (PREFER_STDARG)
va_start (args, format);
@@ -2144,11 +2237,28 @@ rl_message (va_alist)
format = va_arg (args, char *);
#endif
+ if (msg_buf == 0)
+ msg_buf = xmalloc (msg_bufsiz = 128);
+
#if defined (HAVE_VSNPRINTF)
- vsnprintf (msg_buf, sizeof (msg_buf) - 1, format, args);
+ bneed = vsnprintf (msg_buf, msg_bufsiz - 1, format, args);
+ if (bneed >= msg_bufsiz - 1)
+ {
+ msg_bufsiz = bneed + 1;
+ msg_buf = xrealloc (msg_buf, msg_bufsiz);
+ va_end (args);
+
+#if defined (PREFER_STDARG)
+ va_start (args, format);
+#else
+ va_start (args);
+ format = va_arg (args, char *);
+#endif
+ vsnprintf (msg_buf, msg_bufsiz - 1, format, args);
+ }
#else
vsprintf (msg_buf, format, args);
- msg_buf[sizeof(msg_buf) - 1] = '\0'; /* overflow? */
+ msg_buf[msg_bufsiz - 1] = '\0'; /* overflow? */
#endif
va_end (args);
@@ -2157,6 +2267,12 @@ rl_message (va_alist)
rl_save_prompt ();
msg_saved_prompt = 1;
}
+ else if (local_prompt != saved_local_prompt)
+ {
+ FREE (local_prompt);
+ FREE (local_prompt_prefix);
+ local_prompt = (char *)NULL;
+ }
rl_display_prompt = msg_buf;
local_prompt = expand_prompt (msg_buf, &prompt_visible_length,
&prompt_last_invisible,
@@ -2173,8 +2289,11 @@ int
rl_message (format, arg1, arg2)
char *format;
{
+ if (msg_buf == 0)
+ msg_buf = xmalloc (msg_bufsiz = 128);
+
sprintf (msg_buf, format, arg1, arg2);
- msg_buf[sizeof(msg_buf) - 1] = '\0'; /* overflow? */
+ msg_buf[msg_bufsiz - 1] = '\0'; /* overflow? */
rl_display_prompt = msg_buf;
if (saved_local_prompt == 0)
@@ -2182,6 +2301,12 @@ rl_message (format, arg1, arg2)
rl_save_prompt ();
msg_saved_prompt = 1;
}
+ else if (local_prompt != saved_local_prompt)
+ {
+ FREE (local_prompt);
+ FREE (local_prompt_prefix);
+ local_prompt = (char *)NULL;
+ }
local_prompt = expand_prompt (msg_buf, &prompt_visible_length,
&prompt_last_invisible,
&prompt_invis_chars_first_line,
@@ -2318,10 +2443,13 @@ void
_rl_clear_to_eol (count)
int count;
{
+#ifndef __MSDOS__
if (_rl_term_clreol)
tputs (_rl_term_clreol, 1, _rl_output_character_function);
- else if (count)
- space_to_eol (count);
+ else
+#endif
+ if (count)
+ space_to_eol (count);
}
/* Clear to the end of the line using spaces. COUNT is the minimum
@@ -2341,10 +2469,15 @@ space_to_eol (count)
void
_rl_clear_screen ()
{
+#ifndef __DJGPP__
if (_rl_term_clrpag)
tputs (_rl_term_clrpag, 1, _rl_output_character_function);
else
rl_crlf ();
+#else
+ ScreenClear ();
+ ScreenSetCursor (0, 0);
+#endif /* __DJGPP__ */
}
/* Insert COUNT characters from STRING to the output stream at column COL. */
@@ -2353,48 +2486,47 @@ insert_some_chars (string, count, col)
char *string;
int count, col;
{
-#if defined (__MSDOS__) || defined (__MINGW32__)
+ open_some_spaces (col);
_rl_output_some_chars (string, count);
-#else
- /* DEBUGGING */
- if (MB_CUR_MAX == 1 || rl_byte_oriented)
- if (count != col)
- _rl_ttymsg ("debug: insert_some_chars: count (%d) != col (%d)", count, col);
+}
+
+/* Insert COL spaces, keeping the cursor at the same position. We follow the
+ ncurses documentation and use either im/ei with explicit spaces, or IC/ic
+ by itself. We assume there will either be ei or we don't need to use it. */
+static void
+open_some_spaces (col)
+ int col;
+{
+#if !defined (__MSDOS__) && !defined (__MINGW32__)
+ char *buffer;
+ register int i;
/* If IC is defined, then we do not have to "enter" insert mode. */
if (_rl_term_IC)
{
- char *buffer;
-
buffer = tgoto (_rl_term_IC, 0, col);
tputs (buffer, 1, _rl_output_character_function);
- _rl_output_some_chars (string, count);
}
- else
+ else if (_rl_term_im && *_rl_term_im)
{
- register int i;
-
- /* If we have to turn on insert-mode, then do so. */
- if (_rl_term_im && *_rl_term_im)
- tputs (_rl_term_im, 1, _rl_output_character_function);
-
- /* If there is a special command for inserting characters, then
- use that first to open up the space. */
- if (_rl_term_ic && *_rl_term_ic)
- {
- for (i = col; i--; )
- tputs (_rl_term_ic, 1, _rl_output_character_function);
- }
-
- /* Print the text. */
- _rl_output_some_chars (string, count);
-
- /* If there is a string to turn off insert mode, we had best use
- it now. */
+ tputs (_rl_term_im, 1, _rl_output_character_function);
+ /* just output the desired number of spaces */
+ for (i = col; i--; )
+ _rl_output_character_function (' ');
+ /* If there is a string to turn off insert mode, use it now. */
if (_rl_term_ei && *_rl_term_ei)
tputs (_rl_term_ei, 1, _rl_output_character_function);
+ /* and move back the right number of spaces */
+ _rl_backspace (col);
+ }
+ else if (_rl_term_ic && *_rl_term_ic)
+ {
+ /* If there is a special command for inserting characters, then
+ use that first to open up the space. */
+ for (i = col; i--; )
+ tputs (_rl_term_ic, 1, _rl_output_character_function);
}
-#endif /* __MSDOS__ || __MINGW32__ */
+#endif /* !__MSDOS__ && !__MINGW32__ */
}
/* Delete COUNT characters from the display line. */
@@ -2599,10 +2731,8 @@ _rl_col_width (str, start, end, flags)
if (end <= start)
return 0;
if (MB_CUR_MAX == 1 || rl_byte_oriented)
-{
-_rl_ttymsg ("_rl_col_width: called with MB_CUR_MAX == 1");
+ /* this can happen in some cases where it's inconvenient to check */
return (end - start);
-}
memset (&ps, 0, sizeof (mbstate_t));
@@ -2676,7 +2806,7 @@ _rl_ttymsg ("_rl_col_width: called with MB_CUR_MAX == 1");
{
point += tmp;
max -= tmp;
- tmp = wcwidth(wc);
+ tmp = WCWIDTH(wc);
width += (tmp >= 0) ? tmp : 1;
}
}
diff --git a/lib/readline/doc/history.texi b/lib/readline/doc/history.texi
index 64945d86..a991fe5b 100644
--- a/lib/readline/doc/history.texi
+++ b/lib/readline/doc/history.texi
@@ -2,33 +2,25 @@
@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.)
-
@include version.texi
+@c %**end of header (This is for running Texinfo on a region.)
+
@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--2011 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.
+Copyright @copyright{} 1988--2014 Free Software Foundation, Inc.
@quotation
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.3 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 are free to copy and modify
-this GNU manual. Buying copies from GNU Press supports the FSF in
-developing GNU and promoting software freedom.''
+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 quotation
@end copying
@@ -50,12 +42,6 @@ developing GNU and promoting software freedom.''
@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
diff --git a/lib/readline/doc/hstech.texi b/lib/readline/doc/hstech.texi
index 4fc9e8ef..6487f20b 100644
--- a/lib/readline/doc/hstech.texi
+++ b/lib/readline/doc/hstech.texi
@@ -1,7 +1,7 @@
@ignore
This file documents the user interface to the GNU History library.
-Copyright (C) 1988-2011 Free Software Foundation, Inc.
+Copyright (C) 1988-2014 Free Software Foundation, Inc.
Authored by Brian Fox and Chet Ramey.
Permission is granted to make and distribute verbatim copies of this manual
@@ -377,7 +377,7 @@ 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
+If an error occurred in expansion, then @var{output} contains a descriptive
error message.
@end deftypefun
diff --git a/lib/readline/doc/hsuser.texi b/lib/readline/doc/hsuser.texi
index 75df3ee4..69a50163 100644
--- a/lib/readline/doc/hsuser.texi
+++ b/lib/readline/doc/hsuser.texi
@@ -1,7 +1,7 @@
@ignore
This file documents the user interface to the GNU History library.
-Copyright (C) 1988--2011 Free Software Foundation, Inc.
+Copyright (C) 1988--2014 Free Software Foundation, Inc.
Authored by Brian Fox and Chet Ramey.
Permission is granted to make and distribute verbatim copies of this manual
@@ -84,17 +84,18 @@ 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
+When a shell with history enabled 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.
+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 unset, or set to null, a non-numeric value, or
+a numeric value less than zero, the history file is not truncated.
If the @env{HISTTIMEFORMAT} is set, the time stamp information
associated with each history entry is written to the history file,
@@ -141,8 +142,10 @@ history list and history file.
@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
+The first form selects a range of commands from @var{first} to
+@var{last} from the history list and displays or edits and re-executes
+them.
+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
@@ -161,6 +164,7 @@ 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}.
+@var{command} is intepreted the same as @var{first} above.
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}
@@ -208,11 +212,11 @@ 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
+Read the history file and append its contents to
the history list.
@item -w
-Write out the current history to the history file.
+Write out the current history list to the history file.
@item -p
Perform history substitution on the @var{arg}s and display the result
diff --git a/lib/readline/doc/rlman.texi b/lib/readline/doc/rlman.texi
index 1c9ac133..17a8292b 100644
--- a/lib/readline/doc/rlman.texi
+++ b/lib/readline/doc/rlman.texi
@@ -2,34 +2,26 @@
@comment %**start of header (This is for running Texinfo on a region.)
@setfilename readline.info
@settitle GNU Readline Library
+@include version.texi
+
@comment %**end of header (This is for running Texinfo on a region.)
@synindex vr fn
-@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--2011 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.
+Copyright @copyright{} 1988--2014 Free Software Foundation, Inc.
@quotation
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.3 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 are free to copy and modify
-this GNU manual. Buying copies from GNU Press supports the FSF in
-developing GNU and promoting software freedom.''
+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 quotation
@end copying
@@ -50,12 +42,6 @@ developing GNU and promoting software freedom.''
@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
@@ -67,6 +53,7 @@ USA @*
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.
+The Readline home page is @url{http://www.gnu.org/software/readline/}.
@menu
* Command Line Editing:: GNU Readline User's Manual.
diff --git a/lib/readline/doc/rltech.texi b/lib/readline/doc/rltech.texi
index dc272a21..40de49c4 100644
--- a/lib/readline/doc/rltech.texi
+++ b/lib/readline/doc/rltech.texi
@@ -7,7 +7,7 @@ This document describes the GNU Readline Library, a utility for aiding
in the consistency of user interface across discrete programs that need
to provide a command line interface.
-Copyright (C) 1988--2011 Free Software Foundation, Inc.
+Copyright (C) 1988--2014 Free Software Foundation, Inc.
Permission is granted to make and distribute verbatim copies of
this manual provided the copyright notice and this permission notice
@@ -195,7 +195,7 @@ For Readline 4.2, for example, the value of
@node Readline Typedefs
@subsection Readline Typedefs
-For readabilty, we declare a number of new object types, all pointers
+For readability, we declare a number of new object types, all pointers
to functions.
The reason for declaring these new types is to make it easier to write
@@ -440,6 +440,35 @@ If non-zero, Readline will call indirectly through this pointer
to get a character from the input stream. By default, it is set to
@code{rl_getc}, the default Readline character input function
(@pxref{Character Input}).
+In general, an application that sets @var{rl_getc_function} should consider
+setting @var{rl_input_available_hook} as well.
+@end deftypevar
+
+@deftypevar {rl_hook_func_t *} rl_signal_event_hook
+If non-zero, this is the address of a function to call if a read system
+call is interrupted when Readline is reading terminal input.
+@end deftypevar
+
+@deftypevar {rl_hook_func_t *} rl_input_available_hook
+If non-zero, Readline will use this function's return value when it needs
+to determine whether or not there is available input on the current input
+source.
+The default hook checks @code{rl_instream}; if an application is using a
+different input source, it should set the hook appropriately.
+Readline queries for available input when implementing intra-key-sequence
+timeouts during input and incremental searches.
+This may use an application-specific timeout before returning a value;
+Readline uses the value passed to @code{rl_set_keyboard_input_timeout()}
+or the value of the user-settable @var{keyseq-timeout} variable.
+This is designed for use by applications using Readline's callback interface
+(@pxref{Alternate Interface}), which may not use the traditional
+@code{read(2)} and file descriptor interface, or other applications using
+a different input mechanism.
+If an application uses an input mechanism or hook that can potentially exceed
+the value of @var{keyseq-timeout}, it should increase the timeout or set
+this hook appropriately even when not using the callback interface.
+In general, an application that sets @var{rl_getc_function} should consider
+setting @var{rl_input_available_hook} as well.
@end deftypevar
@deftypevar {rl_voidfunc_t *} rl_redisplay_function
@@ -479,6 +508,19 @@ last key binding occurred.
This variable is set to the text of any currently-executing macro.
@end deftypevar
+@deftypevar int rl_executing_key
+The key that caused the dispatch to the currently-executing Readline function.
+@end deftypevar
+
+@deftypevar {char *} rl_executing_keyseq
+The full key sequence that caused the dispatch to the currently-executing
+Readline function.
+@end deftypevar
+
+@deftypevar int rl_key_sequence_length
+The number of characters in @var{rl_executing_keyseq}.
+@end deftypevar
+
@deftypevar {int} rl_readline_state
A variable with bit values that encapsulate the current Readline state.
A bit is set with the @code{RL_SETSTATE} macro, and unset with the
@@ -487,7 +529,7 @@ whether a particular state bit is set. Current state bits include:
@table @code
@item RL_STATE_NONE
-Readline has not yet been called, nor has it begun to intialize.
+Readline has not yet been called, nor has it begun to initialize.
@item RL_STATE_INITIALIZING
Readline is initializing its internal data structures.
@item RL_STATE_INITIALIZED
@@ -580,6 +622,7 @@ means that vi mode is active.
* Miscellaneous Functions:: Functions that don't fall into any category.
* Alternate Interface:: Using Readline in a `callback' fashion.
* A Readline Example:: An example Readline function.
+* Alternate Interface Example:: An example program using the alternate interface.
@end menu
@node Function Naming
@@ -908,7 +951,7 @@ Readline thinks the screen display is correct.
@deftypefun int rl_on_new_line (void)
Tell the update functions that we have moved onto a new (empty) line,
-usually after ouputting a newline.
+usually after outputting a newline.
@end deftypefun
@deftypefun int rl_on_new_line_with_prompt (void)
@@ -1241,21 +1284,29 @@ use all of a terminal's capabilities, and this function will return
values for only those capabilities Readline uses.
@end deftypefun
+@deftypefun {void} rl_clear_history (void)
+Clear the history list by deleting all of the entries, in the same manner
+as the History library's @code{clear_history()} function.
+This differs from @code{clear_history} because it frees private data
+Readline saves in the history list.
+@end deftypefun
+
@node Alternate Interface
@subsection Alternate Interface
An alternate interface is available to plain @code{readline()}. Some
applications need to interleave keyboard I/O with file, device, or
window system I/O, typically by using a main loop to @code{select()}
-on various file descriptors. To accomodate this need, readline can
+on various file descriptors. To accommodate this need, readline can
also be invoked as a `callback' function from an event loop. There
are functions available to make this easy.
@deftypefun void rl_callback_handler_install (const char *prompt, rl_vcpfunc_t *lhandler)
Set up the terminal for readline I/O and display the initial
expanded value of @var{prompt}. Save the value of @var{lhandler} to
-use as a function to call when a complete line of input has been entered.
-The function takes the text of the line as an argument.
+use as a handler function to call when a complete line of input has been
+entered.
+The handler function receives the text of the line as an argument.
@end deftypefun
@deftypefun void rl_callback_read_char (void)
@@ -1263,14 +1314,15 @@ Whenever an application determines that keyboard input is available, it
should call @code{rl_callback_read_char()}, which will read the next
character from the current input source.
If that character completes the line, @code{rl_callback_read_char} will
-invoke the @var{lhandler} function saved by @code{rl_callback_handler_install}
-to process the line.
+invoke the @var{lhandler} function installed by
+@code{rl_callback_handler_install} to process the line.
Before calling the @var{lhandler} function, the terminal settings are
reset to the values they had before calling
@code{rl_callback_handler_install}.
If the @var{lhandler} function returns,
+and the line handler remains installed,
the terminal settings are modified for Readline's use again.
-@code{EOF} is indicated by calling @var{lhandler} with a
+@code{EOF} is indicated by calling @var{lhandler} with a
@code{NULL} line.
@end deftypefun
@@ -1350,6 +1402,98 @@ invert_case_line (count, key)
@}
@end example
+@node Alternate Interface Example
+@subsection Alternate Interface Example
+
+Here is a complete program that illustrates Readline's alternate interface.
+It reads lines from the terminal and displays them, providing the
+standard history and TAB completion functions.
+It understands the EOF character or "exit" to exit the program.
+
+@example
+/* Standard include files. stdio.h is required. */
+#include <stdlib.h>
+#include <unistd.h>
+
+/* Used for select(2) */
+#include <sys/types.h>
+#include <sys/select.h>
+
+#include <stdio.h>
+
+/* Standard readline include files. */
+#include <readline/readline.h>
+#include <readline/history.h>
+
+static void cb_linehandler (char *);
+
+int running;
+const char *prompt = "rltest$ ";
+
+/* Callback function called for each line when accept-line executed, EOF
+ seen, or EOF character read. This sets a flag and returns; it could
+ also call exit(3). */
+static void
+cb_linehandler (char *line)
+@{
+ /* Can use ^D (stty eof) or `exit' to exit. */
+ if (line == NULL || strcmp (line, "exit") == 0)
+ @{
+ if (line == 0)
+ printf ("\n");
+ printf ("exit\n");
+ /* This function needs to be called to reset the terminal settings,
+ and calling it from the line handler keeps one extra prompt from
+ being displayed. */
+ rl_callback_handler_remove ();
+
+ running = 0;
+ @}
+ else
+ @{
+ if (*line)
+ add_history (line);
+ printf ("input line: %s\n", line);
+ free (line);
+ @}
+@}
+
+int
+main (int c, char **v)
+@{
+ fd_set fds;
+ int r;
+
+ /* Install the line handler. */
+ rl_callback_handler_install (prompt, cb_linehandler);
+
+ /* Enter a simple event loop. This waits until something is available
+ to read on readline's input stream (defaults to standard input) and
+ calls the builtin character read callback to read it. It does not
+ have to modify the user's terminal settings. */
+ running = 1;
+ while (running)
+ @{
+ FD_ZERO (&fds);
+ FD_SET (fileno (rl_instream), &fds);
+
+ r = select (FD_SETSIZE, &fds, NULL, NULL, NULL);
+ if (r < 0)
+ @{
+ perror ("rltest: select");
+ rl_callback_handler_remove ();
+ break;
+ @}
+
+ if (FD_ISSET (fileno (rl_instream), &fds))
+ rl_callback_read_char ();
+ @}
+
+ printf ("rltest: Event loop has exited\n");
+ return 0;
+@}
+@end example
+
@node Readline Signal Handling
@section Readline Signal Handling
@@ -1365,6 +1509,7 @@ functions to do so manually.
Readline contains an internal signal handler that is installed for a
number of signals (@code{SIGINT}, @code{SIGQUIT}, @code{SIGTERM},
+@code{SIGHUP},
@code{SIGALRM}, @code{SIGTSTP}, @code{SIGTTIN}, and @code{SIGTTOU}).
When one of these signals is received, the signal handler
will reset the terminal attributes to those that were in effect before
@@ -1397,19 +1542,28 @@ a signal handler, so Readline's internal signal state is not corrupted.
@deftypevar int rl_catch_signals
If this variable is non-zero, Readline will install signal handlers for
-@code{SIGINT}, @code{SIGQUIT}, @code{SIGTERM}, @code{SIGALRM},
+@code{SIGINT}, @code{SIGQUIT}, @code{SIGTERM}, @code{SIGHUP}, @code{SIGALRM},
@code{SIGTSTP}, @code{SIGTTIN}, and @code{SIGTTOU}.
The default value of @code{rl_catch_signals} is 1.
@end deftypevar
@deftypevar int rl_catch_sigwinch
-If this variable is non-zero, Readline will install a signal handler for
-@code{SIGWINCH}.
+If this variable is set to a non-zero value,
+Readline will install a signal handler for @code{SIGWINCH}.
The default value of @code{rl_catch_sigwinch} is 1.
@end deftypevar
+@deftypevar int rl_change_environment
+If this variable is set to a non-zero value,
+and Readline is handling @code{SIGWINCH}, Readline will modify the
+@var{LINES} and @var{COLUMNS} environment variables upon receipt of a
+@code{SIGWINCH}
+
+The default value of @code{rl_change_environment} is 1.
+@end deftypevar
+
If an application does not wish to have Readline catch any signals, or
to handle signals other than those Readline catches (@code{SIGHUP},
for example),
@@ -1477,7 +1631,7 @@ The following functions install and remove Readline's signal handlers.
@deftypefun int rl_set_signals (void)
Install Readline's signal handler for @code{SIGINT}, @code{SIGQUIT},
-@code{SIGTERM}, @code{SIGALRM}, @code{SIGTSTP}, @code{SIGTTIN},
+@code{SIGTERM}, @code{SIGHUP}, @code{SIGALRM}, @code{SIGTSTP}, @code{SIGTTIN},
@code{SIGTTOU}, and @code{SIGWINCH}, depending on the values of
@code{rl_catch_signals} and @code{rl_catch_sigwinch}.
@end deftypefun
@@ -1611,7 +1765,7 @@ This calls @code{rl_complete_internal()} with an argument of @samp{*}.
@end deftypefun
@deftypefun int rl_completion_mode (rl_command_func_t *cfunc)
-Returns the apppriate value to pass to @code{rl_complete_internal()}
+Returns the appropriate value to pass to @code{rl_complete_internal()}
depending on whether @var{cfunc} was called twice in succession and
the values of the @code{show-all-if-ambiguous} and
@code{show-all-if-unmodified} variables.
@@ -1728,29 +1882,45 @@ the directory portion of the pathname the user typed.
At the least, even if no other expansion is performed, this function should
remove any quote characters from the directory name, because its result will
be passed directly to @code{opendir()}.
+
The directory completion hook returns an integer that should be non-zero if
the function modifies its directory argument.
The function should not modify the directory argument if it returns 0.
@end deftypevar
-@ignore
-@deftypevar extern rl_icppfunc_t *rl_directory_rewrite_hook;
+@deftypevar {rl_icppfunc_t *} rl_directory_rewrite_hook;
If non-zero, this is the address of a function to call when completing
a directory name. This function takes the address of the directory name
to be modified as an argument. Unlike @code{rl_directory_completion_hook},
it only modifies the directory name used in @code{opendir}, not what is
displayed when the possible completions are printed or inserted. It is
called before rl_directory_completion_hook.
+At the least, even if no other expansion is performed, this function should
+remove any quote characters from the directory name, because its result will
+be passed directly to @code{opendir()}.
-I'm not happy with how this works yet, so it's undocumented.
+The directory rewrite hook returns an integer that should be non-zero if
+the function modfies its directory argument.
+The function should not modify the directory argument if it returns 0.
+@end deftypevar
+
+@deftypevar {rl_icppfunc_t *} rl_filename_stat_hook
+If non-zero, this is the address of a function for the completer to
+call before deciding which character to append to a completed name.
+This function modifies its filename name argument, and the modified value
+is passed to @code{stat()} to determine the file's type and characteristics.
+This function does not need to remove quote characters from the filename.
+
+The stat hook returns an integer that should be non-zero if
+the function modfies its directory argument.
+The function should not modify the directory argument if it returns 0.
@end deftypevar
-@end ignore
@deftypevar {rl_dequote_func_t *} rl_filename_rewrite_hook
If non-zero, this is the address of a function called when reading
directory entries from the filesystem for completion and comparing
them to the partial word to be completed. The function should
-perform any necesary application or system-specific conversion on
+perform any necessary application or system-specific conversion on
the filename, such as converting between character sets or converting
from a filesystem format to a character input format.
The function takes two arguments: @var{fname}, the filename to be converted,
diff --git a/lib/readline/doc/rluser.texi b/lib/readline/doc/rluser.texi
index 8a69c993..0af6c02e 100644
--- a/lib/readline/doc/rluser.texi
+++ b/lib/readline/doc/rluser.texi
@@ -9,7 +9,7 @@ use these features. There is a document entitled "readline.texinfo"
which contains both end-user and programmer documentation for the
GNU Readline Library.
-Copyright (C) 1988--2011 Free Software Foundation, Inc.
+Copyright (C) 1988--2014 Free Software Foundation, Inc.
Authored by Brian Fox and Chet Ramey.
@@ -72,6 +72,8 @@ Line editing can be enabled at any time using the @option{-o emacs} or
a specific command.
* Programmable Completion Builtins:: Builtin commands to specify how to
complete arguments for a particular command.
+* A Programmable Completion Example:: An example shell function for
+ generating possible completions.
@end ifset
@end menu
@@ -425,6 +427,14 @@ If set to @samp{on}, Readline attempts to bind the control characters
treated specially by the kernel's terminal driver to their Readline
equivalents.
+@item colored-stats
+@vindex colored-stats
+If set to @samp{on}, Readline displays possible completions using different
+colors to indicate their file type.
+The color definitions are taken from the value of the @env{LS_COLORS}
+environment variable.
+The default is @samp{off}.
+
@item comment-begin
@vindex comment-begin
The string to insert at the beginning of the line when the
@@ -521,8 +531,12 @@ or @code{next-history}. The default is @samp{off}.
@item history-size
@vindex history-size
-Set the maximum number of history entries saved in the history list. If
-set to zero, the number of entries in the history list is not limited.
+Set the maximum number of history entries saved in the history list.
+If set to zero, any existing history entries are deleted and no new entries
+are saved.
+If set to a value less than zero, the number of history entries is not
+limited.
+By default, the number of history entries is not limited.
@item horizontal-scroll-mode
@vindex horizontal-scroll-mode
@@ -565,6 +579,22 @@ equivalent to @code{emacs-standard}. The default value is @code{emacs}.
The value of the @code{editing-mode} variable also affects the
default keymap.
+@item keyseq-timeout
+Specifies the duration Readline will wait for a character when reading an
+ambiguous key sequence (one that can form a complete key sequence using
+the input read so far, or can take additional input to complete a longer
+key sequence).
+If no input is received within the timeout, Readline will use the shorter
+but complete key sequence.
+Readline uses this value to determine whether or not input is
+available on the current input source (@code{rl_instream} by default).
+The value is specified in milliseconds, so a value of 1000 means that
+Readline will wait one second for additional input.
+If this variable is set to a value less than or equal to zero, or to a
+non-numeric value, Readline will wait until another key is pressed to
+decide which key sequence to complete.
+The default value is @code{500}.
+
@item mark-directories
If set to @samp{on}, completed directory names have a slash
appended. The default is @samp{on}.
@@ -640,6 +670,13 @@ a common prefix) cause the matches to be listed immediately instead
of ringing the bell.
The default value is @samp{off}.
+@item show-mode-in-prompt
+@vindex show-mode-in-prompt
+If set to @samp{on}, add a character to the beginning of the prompt
+indicating the editing mode: emacs (@samp{@@}), vi command (@samp{:}),
+or vi insertion (@samp{+}).
+The default value is @samp{off}.
+
@item skip-completed-text
@vindex skip-completed-text
If set to @samp{on}, this alters the default completion behavior when
@@ -880,7 +917,7 @@ binding, variable assignment, and conditional syntax.
# You can re-read the inputrc file with C-x C-r.
# Lines beginning with '#' are comments.
#
-# First, include any systemwide bindings and variable
+# First, include any system-wide bindings and variable
# assignments from /etc/Inputrc
$include /etc/Inputrc
@@ -1100,13 +1137,30 @@ for a string supplied by the user.
@item history-search-forward ()
Search forward through the history for the string of characters
between the start of the current line and the point.
+The search string must match at the beginning of a history line.
This is a non-incremental search.
By default, this command is unbound.
@item history-search-backward ()
Search backward through the history for the string of characters
-between the start of the current line and the point. This
-is a non-incremental search. By default, this command is unbound.
+between the start of the current line and the point.
+The search string must match at the beginning of a history line.
+This is a non-incremental search.
+By default, this command is unbound.
+
+@item history-substr-search-forward ()
+Search forward through the history for the string of characters
+between the start of the current line and the point.
+The search string may match anywhere in a history line.
+This is a non-incremental search.
+By default, this command is unbound.
+
+@item history-substr-search-backward ()
+Search backward through the history for the string of characters
+between the start of the current line and the point.
+The search string may match anywhere in a history line.
+This is a non-incremental search.
+By default, this command is unbound.
@item yank-nth-arg (M-C-y)
Insert the first argument to the previous command (usually
@@ -1137,11 +1191,17 @@ as if the @samp{!$} history expansion had been specified.
@subsection Commands For Changing Text
@ftable @code
+
+@item @i{end-of-file} (usually C-d)
+The character indicating end-of-file as set, for example, by
+@code{stty}. If this character is read when there are no characters
+on the line, and point is at the beginning of the line, Readline
+interprets it as the end of input and returns @sc{eof}.
+
@item delete-char (C-d)
-Delete the character at point. If point is at the
-beginning of the line, there are no characters in the line, and
-the last character typed was not bound to @code{delete-char}, then
-return @sc{eof}.
+Delete the character at point. If this function is bound to the
+same character as the tty @sc{eof} character, as @kbd{C-d}
+commonly is, see above for the effects.
@item backward-delete-char (Rubout)
Delete the character behind the cursor. A numeric argument means
@@ -1435,6 +1495,10 @@ and save the definition.
Re-execute the last keyboard macro defined, by making the characters
in the macro appear as if typed at the keyboard.
+@item print-last-kbd-macro ()
+Print the last keboard macro defined in a format suitable for the
+@var{inputrc} file.
+
@end ftable
@node Miscellaneous Commands
@@ -1693,10 +1757,11 @@ When the command or function is invoked, the @env{COMP_LINE},
assigned values as described above (@pxref{Bash Variables}).
If a shell function is being invoked, the @env{COMP_WORDS} and
@env{COMP_CWORD} variables are also set.
-When the function or command is invoked, the first argument is the
+When the function or command is invoked, the first argument ($1) is the
name of the command whose arguments are being completed, the
-second argument is the word being completed, and the third argument
-is the word preceding the word being completed on the current command line.
+second argument ($2) is the word being completed, and the third argument
+($3) is the word preceding the word being completed on the current command
+line.
No filtering of the generated completions against the word being completed
is performed; the function or command has complete freedom in generating
the matches.
@@ -1706,7 +1771,7 @@ The function may use any of the shell facilities, including the
@code{compgen} and @code{compopt} builtins described below
(@pxref{Programmable Completion Builtins}), to generate the matches.
It must put the possible completions in the @env{COMPREPLY} array
-variable.
+variable, one per array element.
Next, any command specified with the @option{-C} option is invoked
in an environment equivalent to command substitution.
@@ -1774,17 +1839,18 @@ completion function would load completions dynamically:
@example
_completion_loader()
@{
- . "/etc/bash_completion.d/$1.sh" >/dev/null 2>&1 && return 124
+ . "/etc/bash_completion.d/$1.sh" >/dev/null 2>&1 && return 124
@}
-complete -D -F _completion_loader
+complete -D -F _completion_loader -o bashdefault -o default
@end example
@node Programmable Completion Builtins
@section Programmable Completion Builtins
@cindex completion builtins
-Two builtin commands are available to manipulate the programmable completion
-facilities.
+Three builtin commands are available to manipulate the programmable completion
+facilities: one to specify how the arguments to a particular command are to
+be completed, and two to modify the completion as it is happening.
@table @code
@item compgen
@@ -1871,6 +1937,10 @@ quoting special characters, or suppressing trailing spaces).
This option is intended to be used with shell functions specified
with @option{-F}.
+@item noquote
+Tell Readline not to quote the completed words if they are filenames
+(quoting filenames is the default).
+
@item nospace
Tell Readline not to append a space (the default) to words completed at
the end of the line.
@@ -1970,6 +2040,10 @@ used as the possible completions.
@item -F @var{function}
The shell function @var{function} is executed in the current shell
environment.
+When it is executed, $1 is the name of the command whose arguments are
+being completed, $2 is the word being completed, and $3 is the word
+preceding the word being completed, as described above
+(@pxref{Programmable Completion}).
When it finishes, the possible completions are retrieved from the value
of the @env{COMPREPLY} array variable.
@@ -2034,4 +2108,122 @@ specification exists, or an output error occurs.
@end table
+@node A Programmable Completion Example
+@section A Programmable Completion Example
+
+The most common way to obtain additional completion functionality beyond
+the default actions @code{complete} and @code{compgen} provide is to use
+a shell function and bind it to a particular command using @code{complete -F}.
+
+The following function provides completions for the @code{cd} builtin.
+It is a reasonably good example of what shell functions must do when
+used for completion. This function uses the word passsed as @code{$2}
+to determine the directory name to complete. You can also use the
+@code{COMP_WORDS} array variable; the current word is indexed by the
+@code{COMP_CWORD} variable.
+
+The function relies on the @code{complete} and @code{compgen} builtins
+to do much of the work, adding only the things that the Bash @code{cd}
+does beyond accepting basic directory names:
+tilde expansion (@pxref{Tilde Expansion}),
+searching directories in @var{$CDPATH}, which is described above
+(@pxref{Bourne Shell Builtins}),
+and basic support for the @code{cdable_vars} shell option
+(@pxref{The Shopt Builtin}).
+@code{_comp_cd} modifies the value of @var{IFS} so that it contains only
+a newline to accommodate file names containing spaces and tabs --
+@code{compgen} prints the possible completions it generates one per line.
+
+Possible completions go into the @var{COMPREPLY} array variable, one
+completion per array element. The programmable completion system retrieves
+the completions from there when the function returns.
+
+@example
+# A completion function for the cd builtin
+# based on the cd completion function from the bash_completion package
+_comp_cd()
+@{
+ local IFS=$' \t\n' # normalize IFS
+ local cur _skipdot _cdpath
+ local i j k
+
+ # Tilde expansion, with side effect of expanding tilde to full pathname
+ case "$2" in
+ \~*) eval cur="$2" ;;
+ *) cur=$2 ;;
+ esac
+
+ # no cdpath or absolute pathname -- straight directory completion
+ if [[ -z "$@{CDPATH:-@}" ]] || [[ "$cur" == @@(./*|../*|/*) ]]; then
+ # compgen prints paths one per line; could also use while loop
+ IFS=$'\n'
+ COMPREPLY=( $(compgen -d -- "$cur") )
+ IFS=$' \t\n'
+ # CDPATH+directories in the current directory if not in CDPATH
+ else
+ IFS=$'\n'
+ _skipdot=false
+ # preprocess CDPATH to convert null directory names to .
+ _cdpath=$@{CDPATH/#:/.:@}
+ _cdpath=$@{_cdpath//::/:.:@}
+ _cdpath=$@{_cdpath/%:/:.@}
+ for i in $@{_cdpath//:/$'\n'@}; do
+ if [[ $i -ef . ]]; then _skipdot=true; fi
+ k="$@{#COMPREPLY[@@]@}"
+ for j in $( compgen -d -- "$i/$cur" ); do
+ COMPREPLY[k++]=$@{j#$i/@} # cut off directory
+ done
+ done
+ $_skipdot || COMPREPLY+=( $(compgen -d -- "$cur") )
+ IFS=$' \t\n'
+ fi
+
+ # variable names if appropriate shell option set and no completions
+ if shopt -q cdable_vars && [[ $@{#COMPREPLY[@@]@} -eq 0 ]]; then
+ COMPREPLY=( $(compgen -v -- "$cur") )
+ fi
+
+ return 0
+@}
+@end example
+
+We install the completion function using the @option{-F} option to
+@code{complete}:
+
+@example
+# Tell readline to quote appropriate and append slashes to directories;
+# use the bash default completion for other arguments
+complete -o filenames -o nospace -o bashdefault -F _comp_cd cd
+@end example
+
+@noindent
+Since we'd like Bash and Readline to take care of some
+of the other details for us, we use several other options to tell Bash
+and Readline what to do. The @option{-o filenames} option tells Readline
+that the possible completions should be treated as filenames, and quoted
+appropriately. That option will also cause Readline to append a slash to
+filenames it can determine are directories (which is why we might want to
+extend @code{_comp_cd} to append a slash if we're using directories found
+via @var{CDPATH}: Readline can't tell those completions are directories).
+The @option{-o nospace} option tells Readline to not append a space
+character to the directory name, in case we want to append to it.
+The @option{-o bashdefault} option brings in the rest of the "Bash default"
+completions -- possible completion that Bash adds to the default Readline
+set. These include things like command name completion, variable completion
+for words beginning with @samp{@{}, completions containing pathname
+expansion patterns (@pxref{Filename Expansion}), and so on.
+
+Once installed using @code{complete}, @code{_comp_cd} will be called every
+time we attempt word completion for a @code{cd} command.
+
+Many more examples -- an extensive collection of completions for most of
+the common GNU, Unix, and Linux commands -- are available as part of the
+bash_completion project. This is installed by default on many GNU/Linux
+distributions. Originally written by Ian Macdonald, the project now lives
+at @url{http://bash-completion.alioth.debian.org/}. There are ports for
+other systems such as Solaris and Mac OS X.
+
+An older version of the bash_completion package is distributed with bash
+in the @file{examples/complete} subdirectory.
+
@end ifset
diff --git a/lib/readline/doc/rluserman.texi b/lib/readline/doc/rluserman.texi
index 3d545204..ba6b0ad8 100644
--- a/lib/readline/doc/rluserman.texi
+++ b/lib/readline/doc/rluserman.texi
@@ -2,33 +2,25 @@
@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.)
-
@include version.texi
+@comment %**end of header (This is for running Texinfo on a region.)
+
@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--2011 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.
+Copyright @copyright{} 1988--2014 Free Software Foundation, Inc.
@quotation
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.3 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 are free to copy and modify
-this GNU manual. Buying copies from GNU Press supports the FSF in
-developing GNU and promoting software freedom.''
+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 quotation
@end copying
@@ -49,12 +41,6 @@ developing GNU and promoting software freedom.''
@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
@@ -66,6 +52,7 @@ USA @*
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.
+The Readline home page is @url{http://www.gnu.org/software/readline/}.
@menu
* Command Line Editing:: GNU Readline User's Manual.
diff --git a/lib/readline/doc/version.texi b/lib/readline/doc/version.texi
index 3ee1c10e..70b66582 100644
--- a/lib/readline/doc/version.texi
+++ b/lib/readline/doc/version.texi
@@ -1,10 +1,10 @@
@ignore
-Copyright (C) 1988-2011 Free Software Foundation, Inc.
+Copyright (C) 1988-2014 Free Software Foundation, Inc.
@end ignore
-@set EDITION 6.2
-@set VERSION 6.2
-@set UPDATED September 6 2010
-@set UPDATED-MONTH September 2010
+@set EDITION 6.3
+@set VERSION 6.3
+@set UPDATED 6 January 2014
+@set UPDATED-MONTH January 2014
-@set LASTCHANGE Mon Sep 6 22:07:10 EDT 2010
+@set LASTCHANGE Mon Jan 6 16:26:51 EST 2014
diff --git a/lib/readline/examples/excallback.c b/lib/readline/examples/excallback.c
index 385492b1..4206acfc 100644
--- a/lib/readline/examples/excallback.c
+++ b/lib/readline/examples/excallback.c
@@ -40,13 +40,14 @@ Copyright (C) 1999 Jeff Solomon
#include <config.h>
#endif
-#include <stdio.h>
#include <sys/types.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
+#include <stdlib.h>
+#include <stdio.h>
#include <termios.h> /* xxx - should make this more general */
#ifdef READLINE_LIBRARY
@@ -55,6 +56,10 @@ Copyright (C) 1999 Jeff Solomon
# include <readline/readline.h>
#endif
+#ifndef STDIN_FILENO
+# define STDIN_FILENO 0
+#endif
+
/* This little examples demonstrates the alternate interface to using readline.
* In the alternate interface, the user maintains control over program flow and
* only calls readline when STDIN is readable. Using the alternate interface,
diff --git a/lib/readline/examples/rl-callbacktest.c b/lib/readline/examples/rl-callbacktest.c
new file mode 100644
index 00000000..a7e451c1
--- /dev/null
+++ b/lib/readline/examples/rl-callbacktest.c
@@ -0,0 +1,81 @@
+/* Standard include files. stdio.h is required. */
+#include <stdlib.h>
+#include <unistd.h>
+
+/* Used for select(2) */
+#include <sys/types.h>
+#include <sys/select.h>
+
+#include <stdio.h>
+
+/* Standard readline include files. */
+#include <readline/readline.h>
+#include <readline/history.h>
+
+static void cb_linehandler (char *);
+
+int running;
+const char *prompt = "rltest$ ";
+
+/* Callback function called for each line when accept-line executed, EOF
+ seen, or EOF character read. This sets a flag and returns; it could
+ also call exit(3). */
+static void
+cb_linehandler (char *line)
+{
+ /* Can use ^D (stty eof) or `exit' to exit. */
+ if (line == NULL || strcmp (line, "exit") == 0)
+ {
+ if (line == 0)
+ printf ("\n");
+ printf ("exit\n");
+ /* This function needs to be called to reset the terminal settings,
+ and calling it from the line handler keeps one extra prompt from
+ being displayed. */
+ rl_callback_handler_remove ();
+
+ running = 0;
+ }
+ else
+ {
+ if (*line)
+ add_history (line);
+ printf ("input line: %s\n", line);
+ free (line);
+ }
+}
+
+int
+main (int c, char **v)
+{
+ fd_set fds;
+ int r;
+
+ /* Install the line handler. */
+ rl_callback_handler_install (prompt, cb_linehandler);
+
+ /* Enter a simple event loop. This waits until something is available
+ to read on readline's input stream (defaults to standard input) and
+ calls the builtin character read callback to read it. It does not
+ have to modify the user's terminal settings. */
+ running = 1;
+ while (running)
+ {
+ FD_ZERO (&fds);
+ FD_SET (fileno (rl_instream), &fds);
+
+ r = select (FD_SETSIZE, &fds, NULL, NULL, NULL);
+ if (r < 0)
+ {
+ perror ("rltest: select");
+ rl_callback_handler_remove ();
+ break;
+ }
+
+ if (FD_ISSET (fileno (rl_instream), &fds))
+ rl_callback_read_char ();
+ }
+
+ printf ("rltest: Event loop has exited\n");
+ return 0;
+}
diff --git a/lib/readline/funmap.c b/lib/readline/funmap.c
index 86e375f6..363507b8 100644
--- a/lib/readline/funmap.c
+++ b/lib/readline/funmap.c
@@ -98,6 +98,8 @@ static const FUNMAP default_funmap[] = {
{ "forward-word", rl_forward_word },
{ "history-search-backward", rl_history_search_backward },
{ "history-search-forward", rl_history_search_forward },
+ { "history-substring-search-backward", rl_history_substr_search_backward },
+ { "history-substring-search-forward", rl_history_substr_search_forward },
{ "insert-comment", rl_insert_comment },
{ "insert-completions", rl_insert_completions },
{ "kill-whole-line", rl_kill_full_line },
@@ -118,6 +120,7 @@ static const FUNMAP default_funmap[] = {
#endif
{ "possible-completions", rl_possible_completions },
{ "previous-history", rl_get_previous_history },
+ { "print-last-kbd-macro", rl_print_last_kbd_macro },
{ "quoted-insert", rl_quoted_insert },
{ "re-read-init-file", rl_re_read_init_file },
{ "redraw-current-line", rl_refresh_line},
@@ -236,7 +239,7 @@ rl_initialize_funmap ()
/* Produce a NULL terminated array of known function names. The array
is sorted. The array itself is allocated, but not the strings inside.
- You should free () the array when you done, but not the pointrs. */
+ You should free () the array when you done, but not the pointers. */
const char **
rl_funmap_names ()
{
diff --git a/lib/readline/histexpand.c b/lib/readline/histexpand.c
index 8fb3798b..4899b9d3 100644
--- a/lib/readline/histexpand.c
+++ b/lib/readline/histexpand.c
@@ -1,6 +1,6 @@
/* histexpand.c -- history expansion. */
-/* Copyright (C) 1989-2010 Free Software Foundation, Inc.
+/* Copyright (C) 1989-2012 Free Software Foundation, Inc.
This file contains the GNU History Library (History), a set of
routines for managing the text of previously typed lines.
@@ -272,6 +272,8 @@ get_history_event (string, caller_index, delimiting_quote)
if (local_index == 0 || substring_okay)
{
entry = current_history ();
+ if (entry == 0)
+ FAIL_SEARCH ();
history_offset = history_length;
/* If this was a substring search, then remember the
@@ -519,9 +521,9 @@ postproc_subst_rhs ()
the returned string. Returns the new index into string in
*END_INDEX_PTR, and the expanded specifier in *RET_STRING. */
static int
-history_expand_internal (string, start, end_index_ptr, ret_string, current_line)
+history_expand_internal (string, start, qc, end_index_ptr, ret_string, current_line)
char *string;
- int start, *end_index_ptr;
+ int start, qc, *end_index_ptr;
char **ret_string;
char *current_line; /* for !# */
{
@@ -557,30 +559,7 @@ history_expand_internal (string, start, end_index_ptr, ret_string, current_line)
event = current_line;
}
else
- {
- int quoted_search_delimiter = 0;
-
- /* If the character before this `!' is a double or single
- quote, then this expansion takes place inside of the
- quoted string. If we have to search for some text ("!foo"),
- allow the delimiter to end the search string. */
-#if defined (HANDLE_MULTIBYTE)
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- {
- int ch, l;
- l = _rl_find_prev_mbchar (string, i, MB_FIND_ANY);
- ch = string[l];
- /* XXX - original patch had i - 1 ??? If i == 0 it would fail. */
- if (i && (ch == '\'' || ch == '"'))
- quoted_search_delimiter = ch;
- }
- else
-#endif /* HANDLE_MULTIBYTE */
- if (i && (string[i - 1] == '\'' || string[i - 1] == '"'))
- quoted_search_delimiter = string[i - 1];
-
- event = get_history_event (string, &i, quoted_search_delimiter);
- }
+ event = get_history_event (string, &i, qc);
if (event == 0)
{
@@ -854,7 +833,7 @@ history_expand_internal (string, start, end_index_ptr, ret_string, current_line)
}
i += 2;
}
- /* Done with modfiers. */
+ /* Done with modifiers. */
/* Believe it or not, we have to back the pointer up by one. */
--i;
@@ -928,7 +907,7 @@ history_expand (hstring, output)
char **output;
{
register int j;
- int i, r, l, passc, cc, modified, eindex, only_printing, dquote, flag;
+ int i, r, l, passc, cc, modified, eindex, only_printing, dquote, squote, flag;
char *string;
/* The output string, and its length. */
@@ -991,7 +970,7 @@ history_expand (hstring, output)
/* `!' followed by one of the characters in history_no_expand_chars
is NOT an expansion. */
- for (i = dquote = 0; string[i]; i++)
+ for (i = dquote = squote = 0; string[i]; i++)
{
#if defined (HANDLE_MULTIBYTE)
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
@@ -1022,6 +1001,13 @@ history_expand (hstring, output)
{
if (cc == 0 || member (cc, history_no_expand_chars))
continue;
+ /* DQUOTE won't be set unless history_quotes_inhibit_expansion
+ is set. The idea here is to treat double-quoted strings the
+ same as the word outside double quotes; in effect making the
+ double quote part of history_no_expand_chars when DQUOTE is
+ set. */
+ else if (dquote && cc == '"')
+ continue;
/* If the calling application has set
history_inhibit_expansion_function to a function that checks
for special cases that should not be history expanded,
@@ -1071,9 +1057,9 @@ history_expand (hstring, output)
}
/* Extract and perform the substitution. */
- for (passc = dquote = i = j = 0; i < l; i++)
+ for (passc = dquote = squote = i = j = 0; i < l; i++)
{
- int tchar = string[i];
+ int qc, tchar = string[i];
if (passc)
{
@@ -1130,8 +1116,14 @@ history_expand (hstring, output)
case '\'':
{
/* If history_quotes_inhibit_expansion is set, single quotes
- inhibit history expansion. */
- if (dquote == 0 && history_quotes_inhibit_expansion)
+ inhibit history expansion, otherwise they are treated like
+ double quotes. */
+ if (squote)
+ {
+ squote = 0;
+ ADD_CHAR (tchar);
+ }
+ else if (dquote == 0 && history_quotes_inhibit_expansion)
{
int quote, slen;
@@ -1146,6 +1138,11 @@ history_expand (hstring, output)
ADD_STRING (temp);
xfree (temp);
}
+ else if (dquote == 0 && squote == 0 && history_quotes_inhibit_expansion == 0)
+ {
+ squote = 1;
+ ADD_CHAR (string[i]);
+ }
else
ADD_CHAR (string[i]);
break;
@@ -1171,6 +1168,7 @@ history_expand (hstring, output)
characters in history_no_expand_chars, then it is not a
candidate for expansion of any kind. */
if (cc == 0 || member (cc, history_no_expand_chars) ||
+ (dquote && cc == '"') ||
(history_inhibit_expansion_function && (*history_inhibit_expansion_function) (string, i)))
{
ADD_CHAR (string[i]);
@@ -1196,8 +1194,8 @@ history_expand (hstring, output)
break;
}
#endif
-
- r = history_expand_internal (string, i, &eindex, &temp, result);
+ qc = squote ? '\'' : (dquote ? '"' : 0);
+ r = history_expand_internal (string, i, qc, &eindex, &temp, result);
if (r < 0)
{
*output = temp;
diff --git a/lib/readline/histfile.c b/lib/readline/histfile.c
index 30a61824..bb743156 100644
--- a/lib/readline/histfile.c
+++ b/lib/readline/histfile.c
@@ -125,14 +125,7 @@ history_filename (filename)
home = sh_get_env_value ("HOME");
if (home == 0)
- {
-#if 0
- home = ".";
- home_len = 1;
-#else
- return (NULL);
-#endif
- }
+ return (NULL);
else
home_len = strlen (home);
@@ -148,6 +141,21 @@ history_filename (filename)
return (return_val);
}
+static char *
+history_backupfile (filename)
+ const char *filename;
+{
+ char *ret;
+ size_t len;
+
+ len = strlen (filename);
+ ret = xmalloc (len + 2);
+ strcpy (ret, filename);
+ ret[len] = '-';
+ ret[len+1] = '\0';
+ return ret;
+}
+
/* Add the contents of FILENAME to the history list, a line at a time.
If FILENAME is NULL, then read from ~/.history. Returns 0 if
successful, or errno if not. */
@@ -403,14 +411,16 @@ history_truncate_file (fname, lines)
truncate to. */
if (bp > buffer && ((file = open (filename, O_WRONLY|O_TRUNC|O_BINARY, 0600)) != -1))
{
- write (file, bp, chars_read - (bp - buffer));
+ if (write (file, bp, chars_read - (bp - buffer)) < 0)
+ rv = errno;
#if defined (__BEOS__)
/* BeOS ignores O_TRUNC. */
ftruncate (file, chars_read - (bp - buffer));
#endif
- close (file);
+ if (close (file) < 0 && rv == 0)
+ rv = errno;
}
truncate_exit:
@@ -430,7 +440,7 @@ history_do_write (filename, nelements, overwrite)
int nelements, overwrite;
{
register int i;
- char *output;
+ char *output, *bakname;
int file, mode, rv;
#ifdef HISTORY_USE_MMAP
size_t cursize;
@@ -440,13 +450,22 @@ history_do_write (filename, nelements, overwrite)
mode = overwrite ? O_WRONLY|O_CREAT|O_TRUNC|O_BINARY : O_WRONLY|O_APPEND|O_BINARY;
#endif
output = history_filename (filename);
+ bakname = (overwrite && output) ? history_backupfile (output) : 0;
+
+ if (output && bakname)
+ rename (output, bakname);
+
file = output ? open (output, mode, 0600) : -1;
rv = 0;
if (file == -1)
{
+ rv = errno;
+ if (output && bakname)
+ rename (bakname, output);
FREE (output);
- return (errno);
+ FREE (bakname);
+ return (rv);
}
#ifdef HISTORY_USE_MMAP
@@ -486,8 +505,11 @@ history_do_write (filename, nelements, overwrite)
{
mmap_error:
rv = errno;
- FREE (output);
close (file);
+ if (output && bakname)
+ rename (bakname, output);
+ FREE (output);
+ FREE (bakname);
return rv;
}
#else
@@ -495,8 +517,11 @@ mmap_error:
if (buffer == 0)
{
rv = errno;
- FREE (output);
close (file);
+ if (output && bakname)
+ rename (bakname, output);
+ FREE (output);
+ FREE (bakname);
return rv;
}
#endif
@@ -524,9 +549,16 @@ mmap_error:
#endif
}
- close (file);
+ if (close (file) < 0 && rv == 0)
+ rv = errno;
+
+ if (rv != 0 && output && bakname)
+ rename (bakname, output);
+ else if (rv == 0 && bakname)
+ unlink (bakname);
FREE (output);
+ FREE (bakname);
return (rv);
}
diff --git a/lib/readline/history.c b/lib/readline/history.c
index d7894cfd..1181e7cc 100644
--- a/lib/readline/history.c
+++ b/lib/readline/history.c
@@ -1,6 +1,6 @@
/* history.c -- standalone history library */
-/* Copyright (C) 1989-2009 Free Software Foundation, Inc.
+/* Copyright (C) 1989-2011 Free Software Foundation, Inc.
This file contains the GNU History Library (History), a set of
routines for managing the text of previously typed lines.
@@ -236,7 +236,7 @@ history_get_time (hist)
ts = hist->timestamp;
if (ts[0] != history_comment_char)
return 0;
- t = (time_t) atol (ts + 1); /* XXX - should use strtol() here */
+ t = (time_t) strtol (ts + 1, (char **)NULL, 10); /* XXX - should use strtol() here */
return t;
}
@@ -318,7 +318,7 @@ add_history_time (string)
{
HIST_ENTRY *hs;
- if (string == 0)
+ if (string == 0 || history_length < 1)
return;
hs = the_history[history_length - 1];
FREE (hs->timestamp);
@@ -394,7 +394,7 @@ replace_history_entry (which, line, data)
WHICH >= 0 means to replace that particular history entry's data, as
long as it matches OLD. */
void
-replace_history_data (which,old, new)
+replace_history_data (which, old, new)
int which;
histdata_t *old, *new;
{
diff --git a/lib/readline/history.h b/lib/readline/history.h
index 1257e66c..c8af47e5 100644
--- a/lib/readline/history.h
+++ b/lib/readline/history.h
@@ -216,7 +216,7 @@ extern int history_truncate_file PARAMS((const char *, int));
-1) If there was an error in expansion.
2) If the returned line should just be printed.
- If an error ocurred in expansion, then OUTPUT contains a descriptive
+ If an error occurred in expansion, then OUTPUT contains a descriptive
error message. */
extern int history_expand PARAMS((char *, char **));
diff --git a/lib/readline/input.c b/lib/readline/input.c
index b49af889..117dfe82 100644
--- a/lib/readline/input.c
+++ b/lib/readline/input.c
@@ -1,6 +1,6 @@
/* input.c -- character input functions for readline. */
-/* Copyright (C) 1994-2010 Free Software Foundation, Inc.
+/* Copyright (C) 1994-2013 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.
@@ -45,6 +45,8 @@
# include "ansi_stdlib.h"
#endif /* HAVE_STDLIB_H */
+#include <signal.h>
+
#include "posixselect.h"
#if defined (FIONREAD_IN_SYS_IOCTL)
@@ -78,6 +80,13 @@ extern int errno;
character input. */
rl_hook_func_t *rl_event_hook = (rl_hook_func_t *)NULL;
+/* A function to call if a read(2) is interrupted by a signal. */
+rl_hook_func_t *rl_signal_event_hook = (rl_hook_func_t *)NULL;
+
+/* A function to replace _rl_input_available for applications using the
+ callback interface. */
+rl_hook_func_t *rl_input_available_hook = (rl_hook_func_t *)NULL;
+
rl_getc_func_t *rl_getc_function = rl_getc;
static int _keyboard_input_timeout = 100000; /* 0.1 seconds; it's in usec */
@@ -104,6 +113,12 @@ _rl_any_typein ()
return any_typein;
}
+int
+_rl_pushed_input_available ()
+{
+ return (push_index != pop_index);
+}
+
/* Return the amount of space available in the buffer for stuffing
characters. */
static int
@@ -117,7 +132,7 @@ ibuffer_space ()
/* Get a key from the buffer of characters to be read.
Return the key in KEY.
- Result is KEY if there was a key, or 0 if there wasn't. */
+ Result is non-zero if there was a key, or 0 if there wasn't. */
static int
rl_get_char (key)
int *key;
@@ -154,12 +169,6 @@ _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). */
@@ -291,6 +300,9 @@ _rl_input_available ()
#endif
int tty;
+ if (rl_input_available_hook)
+ return (*rl_input_available_hook) ();
+
tty = fileno (rl_instream);
#if defined (HAVE_SELECT)
@@ -411,8 +423,6 @@ rl_read_key ()
{
int c, r;
- rl_key_sequence_length++;
-
if (rl_pending_input)
{
c = rl_pending_input;
@@ -437,7 +447,7 @@ rl_read_key ()
rl_done = 1;
return ('\n');
}
- else if (r == 1) /* read something */
+ else if (r > 0) /* read something */
continue;
RL_CHECK_SIGNALS ();
@@ -450,6 +460,7 @@ rl_read_key ()
{
if (rl_get_char (&c) == 0)
c = (*rl_getc_function) (rl_instream);
+/* fprintf(stderr, "rl_read_key: calling RL_CHECK_SIGNALS: _rl_caught_signal = %d", _rl_caught_signal); */
RL_CHECK_SIGNALS ();
}
}
@@ -468,6 +479,8 @@ rl_getc (stream)
{
RL_CHECK_SIGNALS ();
+ /* We know at this point that _rl_caught_signal == 0 */
+
#if defined (__MINGW32__)
if (isatty (fileno (stream)))
return (getch ());
@@ -509,11 +522,23 @@ rl_getc (stream)
#undef X_EWOULDBLOCK
#undef X_EAGAIN
- /* If the error that we received was SIGINT, then try again,
- this is simply an interrupted system call to read ().
- Otherwise, some error ocurred, also signifying EOF. */
+/* fprintf(stderr, "rl_getc: result = %d errno = %d\n", result, errno); */
+
+ /* If the error that we received was EINTR, then try again,
+ this is simply an interrupted system call to read (). We allow
+ the read to be interrupted if we caught SIGHUP or SIGTERM (but
+ not SIGINT; let the signal handler deal with that), but if the
+ application sets an event hook, call it for other signals.
+ Otherwise (not EINTR), some error occurred, also signifying EOF. */
if (errno != EINTR)
return (RL_ISSTATE (RL_STATE_READCMD) ? READERR : EOF);
+ else if (_rl_caught_signal == SIGHUP || _rl_caught_signal == SIGTERM)
+ return (RL_ISSTATE (RL_STATE_READCMD) ? READERR : EOF);
+ else if (_rl_caught_signal == SIGINT || _rl_caught_signal == SIGQUIT)
+ RL_CHECK_SIGNALS ();
+
+ if (rl_signal_event_hook)
+ (*rl_signal_event_hook) ();
}
}
diff --git a/lib/readline/isearch.c b/lib/readline/isearch.c
index 712b9ea8..6f6a7a65 100644
--- a/lib/readline/isearch.c
+++ b/lib/readline/isearch.c
@@ -6,7 +6,7 @@
/* */
/* **************************************************************** */
-/* Copyright (C) 1987-2009 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2012 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.
@@ -110,7 +110,7 @@ _rl_scxt_alloc (type, flags)
cxt->history_pos = 0;
cxt->direction = 0;
- cxt->lastc = 0;
+ cxt->prevc = cxt->lastc = 0;
cxt->sline = 0;
cxt->sline_len = cxt->sline_index = 0;
@@ -156,16 +156,16 @@ rl_forward_search_history (sign, key)
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)
+rl_display_search (search_string, flags, where)
char *search_string;
- int reverse_p, where;
+ int flags, where;
{
char *message;
int msglen, searchlen;
searchlen = (search_string && *search_string) ? strlen (search_string) : 0;
- message = (char *)xmalloc (searchlen + 33);
+ message = (char *)xmalloc (searchlen + 64);
msglen = 0;
#if defined (NOTDEF)
@@ -178,7 +178,13 @@ rl_display_search (search_string, reverse_p, where)
message[msglen++] = '(';
- if (reverse_p)
+ if (flags & SF_FAILED)
+ {
+ strcpy (message + msglen, "failed ");
+ msglen += 7;
+ }
+
+ if (flags & SF_REVERSE)
{
strcpy (message + msglen, "reverse-");
msglen += 8;
@@ -215,7 +221,7 @@ _rl_isearch_init (direction)
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. */
+ /* Create an array of pointers to the lines that we want to search. */
hlist = history_list ();
rl_maybe_replace_line ();
i = 0;
@@ -312,13 +318,19 @@ _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
+ RL_CHECK_SIGNALS ();
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. */
@@ -344,13 +356,43 @@ _rl_isearch_dispatch (cxt, c)
incremental search, so we check */
if (c >= 0 && cxt->keymap[c].type == ISKMAP && strchr (cxt->search_terminators, cxt->lastc) == 0)
{
+ /* _rl_keyseq_timeout specified in milliseconds; _rl_input_queued
+ takes microseconds, so multiply by 1000. If we don't get any
+ additional input and this keymap shadows another function, process
+ that key as if it was all we read. */
+ if (_rl_keyseq_timeout > 0 &&
+ RL_ISSTATE (RL_STATE_CALLBACK) == 0 &&
+ RL_ISSTATE (RL_STATE_INPUTPENDING) == 0 &&
+ _rl_pushed_input_available () == 0 &&
+ ((Keymap)(cxt->keymap[c].function))[ANYOTHERKEY].function &&
+ _rl_input_queued (_rl_keyseq_timeout*1000) == 0)
+ goto add_character;
+
+ cxt->okeymap = cxt->keymap;
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. */
+ 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;
}
+add_character:
+
/* Translate the keys we do something with to opcodes. */
if (c >= 0 && cxt->keymap[c].type == ISFUNC)
{
@@ -376,6 +418,54 @@ _rl_isearch_dispatch (cxt, c)
{
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);
+ /* XXX - do we insert everything in cxt->pmb? */
+ 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 &&
+ (f == 0 || f == rl_insert))
+ {
+ /* 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 */
+ 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;
+ }
+ else if (cxt->lastc > 0 && cxt->prevc > 0 && f && f != rl_insert)
+ {
+ rl_stuff_char (cxt->lastc);
+ rl_execute_next (cxt->prevc);
+ /* XXX - do we insert everything in cxt->pmb? */
+ return (0);
+ }
}
/* The characters in isearch_terminators (set from the user-settable
@@ -393,14 +483,11 @@ _rl_isearch_dispatch (cxt, c)
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 ())
+ if (cxt->lastc == ESC && (_rl_pushed_input_available () || _rl_input_available ()))
rl_execute_next (ESC);
return (0);
}
-#define ENDSRCH_CHAR(c) \
- ((CTRL_CHAR (c) || META_CHAR (c) || (c) == RUBOUT) && ((c) != CTRL ('G')))
-
#if defined (HANDLE_MULTIBYTE)
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
{
@@ -436,7 +523,7 @@ _rl_isearch_dispatch (cxt, c)
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);
+ rl_display_search (cxt->search_string, cxt->sflags, -1);
break;
}
return (1);
@@ -544,12 +631,16 @@ _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
- cxt->search_string[cxt->search_string_index++] = c;
+ cxt->search_string[cxt->search_string_index++] = cxt->lastc; /* XXX - was c instead of lastc */
cxt->search_string[cxt->search_string_index] = '\0';
break;
}
@@ -606,6 +697,7 @@ _rl_isearch_dispatch (cxt, c)
/* We cannot find the search string. Ding the bell. */
rl_ding ();
cxt->history_pos = cxt->last_found_line;
+ rl_display_search (cxt->search_string, cxt->sflags, (cxt->history_pos == cxt->save_line) ? -1 : cxt->history_pos);
return 1;
}
@@ -618,7 +710,7 @@ _rl_isearch_dispatch (cxt, c)
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);
+ rl_display_search (cxt->search_string, cxt->sflags, (cxt->history_pos == cxt->save_line) ? -1 : cxt->history_pos);
}
return 1;
@@ -653,7 +745,7 @@ rl_search_history (direction, invoking_key)
RL_SETSTATE(RL_STATE_ISEARCH);
cxt = _rl_isearch_init (direction);
- rl_display_search (cxt->search_string, (cxt->sflags & SF_REVERSE), -1);
+ rl_display_search (cxt->search_string, cxt->sflags, -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. */
diff --git a/lib/readline/macro.c b/lib/readline/macro.c
index c2fac8ad..b99a1a69 100644
--- a/lib/readline/macro.c
+++ b/lib/readline/macro.c
@@ -121,6 +121,19 @@ _rl_next_macro_key ()
#endif
}
+int
+_rl_prev_macro_key ()
+{
+ if (rl_executing_macro == 0)
+ return (0);
+
+ if (executing_macro_index == 0)
+ return (0);
+
+ executing_macro_index--;
+ return (rl_executing_macro[executing_macro_index]);
+}
+
/* Save the currently executing macro on a stack of saved macros. */
void
_rl_push_executing_macro ()
@@ -234,7 +247,7 @@ rl_end_kbd_macro (count, ignore)
return -1;
}
- current_macro_index -= rl_key_sequence_length - 1;
+ current_macro_index -= rl_key_sequence_length;
current_macro[current_macro_index] = '\0';
RL_UNSETSTATE(RL_STATE_MACRODEF);
@@ -263,6 +276,29 @@ rl_call_last_kbd_macro (count, ignore)
return 0;
}
+int
+rl_print_last_kbd_macro (count, ignore)
+ int count, ignore;
+{
+ char *m;
+
+ if (current_macro == 0)
+ {
+ rl_ding ();
+ return 0;
+ }
+ m = _rl_untranslate_macro_value (current_macro, 1);
+ rl_crlf ();
+ printf ("%s", m);
+ fflush (stdout);
+ rl_crlf ();
+ FREE (m);
+ rl_forced_update_display ();
+ rl_display_fixed = 1;
+
+ return 0;
+}
+
void
rl_push_macro_input (macro)
char *macro;
diff --git a/lib/readline/mbutil.c b/lib/readline/mbutil.c
index eeb7e557..b036e0c3 100644
--- a/lib/readline/mbutil.c
+++ b/lib/readline/mbutil.c
@@ -64,6 +64,9 @@ int rl_byte_oriented = 0;
int rl_byte_oriented = 1;
#endif
+/* Ditto */
+int _rl_utf8locale = 0;
+
/* **************************************************************** */
/* */
/* Multibyte Character Utility Functions */
@@ -119,7 +122,7 @@ _rl_find_next_mbchar_internal (string, seed, count, find_non_zero)
point += tmp;
if (find_non_zero)
{
- if (wcwidth (wc) == 0)
+ if (WCWIDTH (wc) == 0)
continue;
else
count--;
@@ -132,7 +135,7 @@ _rl_find_next_mbchar_internal (string, seed, count, find_non_zero)
if (find_non_zero)
{
tmp = mbrtowc (&wc, string + point, strlen (string + point), &ps);
- while (MB_NULLWCH (tmp) == 0 && MB_INVALIDCH (tmp) == 0 && wcwidth (wc) == 0)
+ while (MB_NULLWCH (tmp) == 0 && MB_INVALIDCH (tmp) == 0 && WCWIDTH (wc) == 0)
{
point += tmp;
tmp = mbrtowc (&wc, string + point, strlen (string + point), &ps);
@@ -184,7 +187,7 @@ _rl_find_prev_mbchar_internal (string, seed, find_non_zero)
{
if (find_non_zero)
{
- if (wcwidth (wc) != 0)
+ if (WCWIDTH (wc) != 0)
prev = point;
}
else
@@ -263,7 +266,7 @@ _rl_compare_chars (buf1, pos1, ps1, buf2, pos2, ps2)
if point is invalied (point < 0 || more than string length),
it returns -1 */
int
-_rl_adjust_point(string, point, ps)
+_rl_adjust_point (string, point, ps)
char *string;
int point;
mbstate_t *ps;
diff --git a/lib/readline/misc.c b/lib/readline/misc.c
index 9f457736..da5c6964 100644
--- a/lib/readline/misc.c
+++ b/lib/readline/misc.c
@@ -1,6 +1,6 @@
/* misc.c -- miscellaneous bindable readline functions. */
-/* Copyright (C) 1987-2009 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2012 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.
@@ -56,6 +56,8 @@
static int rl_digit_loop PARAMS((void));
static void _rl_history_set_point PARAMS((void));
+extern int history_offset;
+
/* Forward declarations used in this file */
void _rl_free_history_entry PARAMS((HIST_ENTRY *));
@@ -483,6 +485,37 @@ _rl_revert_all_lines ()
xfree (lbuf);
}
+/* Free the history list, including private readline data and take care
+ of pointer aliases to history data. Resets rl_undo_list if it points
+ to an UNDO_LIST * saved as some history entry's data member. This
+ should not be called while editing is active. */
+void
+rl_clear_history ()
+{
+ HIST_ENTRY **hlist, *hent;
+ register int i;
+ UNDO_LIST *ul, *saved_undo_list;
+
+ saved_undo_list = rl_undo_list;
+ hlist = history_list (); /* direct pointer, not copy */
+
+ for (i = 0; i < history_length; i++)
+ {
+ hent = hlist[i];
+ if (ul = (UNDO_LIST *)hent->data)
+ {
+ if (ul == saved_undo_list)
+ saved_undo_list = 0;
+ _rl_free_undo_list (ul);
+ hent->data = 0;
+ }
+ _rl_free_history_entry (hent);
+ }
+
+ history_offset = history_length = 0;
+ rl_undo_list = saved_undo_list; /* should be NULL */
+}
+
/* **************************************************************** */
/* */
/* History Commands */
@@ -623,6 +656,10 @@ rl_emacs_editing_mode (count, key)
rl_editing_mode = emacs_mode;
_rl_set_insert_mode (RL_IM_INSERT, 1); /* emacs mode default is insert mode */
_rl_keymap = emacs_standard_keymap;
+
+ if (_rl_show_mode_in_prompt)
+ _rl_reset_prompt ();
+
return 0;
}
diff --git a/lib/readline/nls.c b/lib/readline/nls.c
index e3599eb7..d3b36344 100644
--- a/lib/readline/nls.c
+++ b/lib/readline/nls.c
@@ -43,6 +43,10 @@
# include <locale.h>
#endif
+#if defined (HAVE_LANGINFO_CODESET)
+# include <langinfo.h>
+#endif
+
#include <ctype.h>
#include "rldefs.h"
@@ -50,6 +54,8 @@
#include "rlshell.h"
#include "rlprivate.h"
+static int utf8locale PARAMS((char *));
+
#if !defined (HAVE_SETLOCALE)
/* A list of legal values for the LANG or LC_CTYPE environment variables.
If a locale name in this list is the value for the LC_ALL, LC_CTYPE,
@@ -72,9 +78,10 @@ static char *legal_lang_values[] =
};
static char *normalize_codeset PARAMS((char *));
-static char *find_codeset PARAMS((char *, size_t *));
#endif /* !HAVE_SETLOCALE */
+static char *find_codeset PARAMS((char *, size_t *));
+
static char *_rl_get_locale_var PARAMS((const char *));
static char *
@@ -91,7 +98,26 @@ _rl_get_locale_var (v)
return lspec;
}
-
+
+static int
+utf8locale (lspec)
+ char *lspec;
+{
+ char *cp;
+ size_t len;
+
+#if HAVE_LANGINFO_CODESET
+ cp = nl_langinfo (CODESET);
+ return (STREQ (cp, "UTF-8") || STREQ (cp, "utf8"));
+#else
+ cp = find_codeset (lspec, &len);
+
+ if (cp == 0 || len < 4 || len > 5)
+ return 0;
+ return ((len == 5) ? strncmp (cp, "UTF-8", len) == 0 : strncmp (cp, "utf8", 4) == 0);
+#endif
+}
+
/* 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. */
@@ -116,6 +142,9 @@ _rl_init_eightbit ()
lspec = "";
t = setlocale (LC_CTYPE, lspec);
+ if (t && *t)
+ _rl_utf8locale = utf8locale (t);
+
if (t && *t && (t[0] != 'C' || t[1]) && (STREQ (t, "POSIX") == 0))
{
_rl_meta_flag = 1;
@@ -197,6 +226,7 @@ normalize_codeset (codeset)
return retval;
}
+#endif /* !HAVE_SETLOCALE */
/* Isolate codeset portion of locale specification. */
static char *
@@ -249,4 +279,3 @@ find_codeset (name, lenp)
return result;
}
-#endif /* !HAVE_SETLOCALE */
diff --git a/lib/readline/parse-colors.c b/lib/readline/parse-colors.c
new file mode 100644
index 00000000..98b2e9d1
--- /dev/null
+++ b/lib/readline/parse-colors.c
@@ -0,0 +1,440 @@
+/* `dir', `vdir' and `ls' directory listing programs for GNU.
+
+ Modified by Chet Ramey for Readline.
+
+ Copyright (C) 1985, 1988, 1990-1991, 1995-2010, 2012 Free Software Foundation,
+ Inc.
+
+ 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 3 of the License, 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, see <http://www.gnu.org/licenses/>. */
+
+/* Written by Richard Stallman and David MacKenzie. */
+
+/* Color support by Peter Anvin <Peter.Anvin@linux.org> and Dennis
+ Flaherty <dennisf@denix.elk.miles.com> based on original patches by
+ Greg Lee <lee@uhunix.uhcc.hawaii.edu>. */
+
+#define READLINE_LIBRARY
+
+#if defined (HAVE_CONFIG_H)
+# include <config.h>
+#endif
+
+#include <stdio.h>
+
+// strdup() / strcpy()
+#if defined (HAVE_STRING_H)
+# include <string.h>
+#else /* !HAVE_STRING_H */
+# include <strings.h>
+#endif /* !HAVE_STRING_H */
+
+// abort()
+#if defined (HAVE_STDLIB_H)
+# include <stdlib.h>
+#else
+# include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+
+#include "rldefs.h" // STREQ, savestring
+#include "readline.h"
+#include "rlprivate.h"
+#include "rlshell.h"
+#include "xmalloc.h"
+
+#include "colors.h"
+#include "parse-colors.h"
+
+#if defined (COLOR_SUPPORT)
+
+static bool get_funky_string (char **dest, const char **src, bool equals_end, size_t *output_count);
+
+struct bin_str _rl_color_indicator[] =
+ {
+ { LEN_STR_PAIR ("\033[") }, // lc: Left of color sequence
+ { LEN_STR_PAIR ("m") }, // rc: Right of color sequence
+ { 0, NULL }, // ec: End color (replaces lc+no+rc)
+ { LEN_STR_PAIR ("0") }, // rs: Reset to ordinary colors
+ { 0, NULL }, // no: Normal
+ { 0, NULL }, // fi: File: default
+ { LEN_STR_PAIR ("01;34") }, // di: Directory: bright blue
+ { LEN_STR_PAIR ("01;36") }, // ln: Symlink: bright cyan
+ { LEN_STR_PAIR ("33") }, // pi: Pipe: yellow/brown
+ { LEN_STR_PAIR ("01;35") }, // so: Socket: bright magenta
+ { LEN_STR_PAIR ("01;33") }, // bd: Block device: bright yellow
+ { LEN_STR_PAIR ("01;33") }, // cd: Char device: bright yellow
+ { 0, NULL }, // mi: Missing file: undefined
+ { 0, NULL }, // or: Orphaned symlink: undefined
+ { LEN_STR_PAIR ("01;32") }, // ex: Executable: bright green
+ { LEN_STR_PAIR ("01;35") }, // do: Door: bright magenta
+ { LEN_STR_PAIR ("37;41") }, // su: setuid: white on red
+ { LEN_STR_PAIR ("30;43") }, // sg: setgid: black on yellow
+ { LEN_STR_PAIR ("37;44") }, // st: sticky: black on blue
+ { LEN_STR_PAIR ("34;42") }, // ow: other-writable: blue on green
+ { LEN_STR_PAIR ("30;42") }, // tw: ow w/ sticky: black on green
+ { LEN_STR_PAIR ("30;41") }, // ca: black on red
+ { 0, NULL }, // mh: disabled by default
+ { LEN_STR_PAIR ("\033[K") }, // cl: clear to end of line
+ };
+
+/* Parse a string as part of the LS_COLORS variable; this may involve
+ decoding all kinds of escape characters. If equals_end is set an
+ unescaped equal sign ends the string, otherwise only a : or \0
+ does. Set *OUTPUT_COUNT to the number of bytes output. Return
+ true if successful.
+
+ The resulting string is *not* null-terminated, but may contain
+ embedded nulls.
+
+ Note that both dest and src are char **; on return they point to
+ the first free byte after the array and the character that ended
+ the input string, respectively. */
+
+static bool
+get_funky_string (char **dest, const char **src, bool equals_end, size_t *output_count) {
+ char num; /* For numerical codes */
+ size_t count; /* Something to count with */
+ enum {
+ ST_GND, ST_BACKSLASH, ST_OCTAL, ST_HEX, ST_CARET, ST_END, ST_ERROR
+ } state;
+ const char *p;
+ char *q;
+
+ p = *src; /* We don't want to double-indirect */
+ q = *dest; /* the whole darn time. */
+
+ count = 0; /* No characters counted in yet. */
+ num = 0;
+
+ state = ST_GND; /* Start in ground state. */
+ while (state < ST_END)
+ {
+ switch (state)
+ {
+ case ST_GND: /* Ground state (no escapes) */
+ switch (*p)
+ {
+ case ':':
+ case '\0':
+ state = ST_END; /* End of string */
+ break;
+ case '\\':
+ state = ST_BACKSLASH; /* Backslash scape sequence */
+ ++p;
+ break;
+ case '^':
+ state = ST_CARET; /* Caret escape */
+ ++p;
+ break;
+ case '=':
+ if (equals_end)
+ {
+ state = ST_END; /* End */
+ break;
+ }
+ /* else fall through */
+ default:
+ *(q++) = *(p++);
+ ++count;
+ break;
+ }
+ break;
+
+ case ST_BACKSLASH: /* Backslash escaped character */
+ switch (*p)
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ state = ST_OCTAL; /* Octal sequence */
+ num = *p - '0';
+ break;
+ case 'x':
+ case 'X':
+ state = ST_HEX; /* Hex sequence */
+ num = 0;
+ break;
+ case 'a': /* Bell */
+ num = '\a';
+ break;
+ case 'b': /* Backspace */
+ num = '\b';
+ break;
+ case 'e': /* Escape */
+ num = 27;
+ break;
+ case 'f': /* Form feed */
+ num = '\f';
+ break;
+ case 'n': /* Newline */
+ num = '\n';
+ break;
+ case 'r': /* Carriage return */
+ num = '\r';
+ break;
+ case 't': /* Tab */
+ num = '\t';
+ break;
+ case 'v': /* Vtab */
+ num = '\v';
+ break;
+ case '?': /* Delete */
+ num = 127;
+ break;
+ case '_': /* Space */
+ num = ' ';
+ break;
+ case '\0': /* End of string */
+ state = ST_ERROR; /* Error! */
+ break;
+ default: /* Escaped character like \ ^ : = */
+ num = *p;
+ break;
+ }
+ if (state == ST_BACKSLASH)
+ {
+ *(q++) = num;
+ ++count;
+ state = ST_GND;
+ }
+ ++p;
+ break;
+
+ case ST_OCTAL: /* Octal sequence */
+ if (*p < '0' || *p > '7')
+ {
+ *(q++) = num;
+ ++count;
+ state = ST_GND;
+ }
+ else
+ num = (num << 3) + (*(p++) - '0');
+ break;
+
+ case ST_HEX: /* Hex sequence */
+ switch (*p)
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ num = (num << 4) + (*(p++) - '0');
+ break;
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f':
+ num = (num << 4) + (*(p++) - 'a') + 10;
+ break;
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':
+ num = (num << 4) + (*(p++) - 'A') + 10;
+ break;
+ default:
+ *(q++) = num;
+ ++count;
+ state = ST_GND;
+ break;
+ }
+ break;
+
+ case ST_CARET: /* Caret escape */
+ state = ST_GND; /* Should be the next state... */
+ if (*p >= '@' && *p <= '~')
+ {
+ *(q++) = *(p++) & 037;
+ ++count;
+ }
+ else if (*p == '?')
+ {
+ *(q++) = 127;
+ ++count;
+ }
+ else
+ state = ST_ERROR;
+ break;
+
+ default:
+ /* should we ? */
+ /* abort (); no, we should not */
+ state = ST_ERROR;
+ break;
+ }
+ }
+
+ *dest = q;
+ *src = p;
+ *output_count = count;
+
+ return state != ST_ERROR;
+}
+#endif /* COLOR_SUPPORT */
+
+void _rl_parse_colors()
+{
+#if defined (COLOR_SUPPORT)
+ const char *p; /* Pointer to character being parsed */
+ char *buf; /* color_buf buffer pointer */
+ int state; /* State of parser */
+ int ind_no; /* Indicator number */
+ char label[3]; /* Indicator label */
+ COLOR_EXT_TYPE *ext; /* Extension we are working on */
+
+ p = sh_get_env_value ("LS_COLORS");
+ if (p == 0 || *p == '\0')
+ {
+ _rl_color_ext_list = NULL;
+ return;
+ }
+
+ ext = NULL;
+ strcpy (label, "??");
+
+ /* This is an overly conservative estimate, but any possible
+ LS_COLORS string will *not* generate a color_buf longer than
+ itself, so it is a safe way of allocating a buffer in
+ advance. */
+ buf = color_buf = savestring (p);
+
+ state = 1;
+ while (state > 0)
+ {
+ switch (state)
+ {
+ case 1: /* First label character */
+ switch (*p)
+ {
+ case ':':
+ ++p;
+ break;
+
+ case '*':
+ /* Allocate new extension block and add to head of
+ linked list (this way a later definition will
+ override an earlier one, which can be useful for
+ having terminal-specific defs override global). */
+
+ ext = (COLOR_EXT_TYPE *)xmalloc (sizeof *ext);
+ ext->next = _rl_color_ext_list;
+ _rl_color_ext_list = ext;
+
+ ++p;
+ ext->ext.string = buf;
+
+ state = (get_funky_string (&buf, &p, true, &ext->ext.len)
+ ? 4 : -1);
+ break;
+
+ case '\0':
+ state = 0; /* Done! */
+ break;
+
+ default: /* Assume it is file type label */
+ label[0] = *(p++);
+ state = 2;
+ break;
+ }
+ break;
+
+ case 2: /* Second label character */
+ if (*p)
+ {
+ label[1] = *(p++);
+ state = 3;
+ }
+ else
+ state = -1; /* Error */
+ break;
+
+ case 3: /* Equal sign after indicator label */
+ state = -1; /* Assume failure... */
+ if (*(p++) == '=')/* It *should* be... */
+ {
+ for (ind_no = 0; indicator_name[ind_no] != NULL; ++ind_no)
+ {
+ if (STREQ (label, indicator_name[ind_no]))
+ {
+ _rl_color_indicator[ind_no].string = buf;
+ state = (get_funky_string (&buf, &p, false,
+ &_rl_color_indicator[ind_no].len)
+ ? 1 : -1);
+ break;
+ }
+ }
+ if (state == -1)
+ {
+ _rl_errmsg ("LS_COLORS: unrecognized prefix: %s", label);
+ /* recover from an unrecognized prefix */
+ while (p && *p && *p != ':')
+ p++;
+ if (p && *p == ':')
+ state = 1;
+ else if (p && *p == 0)
+ state = 0;
+ }
+ }
+ break;
+
+ case 4: /* Equal sign after *.ext */
+ if (*(p++) == '=')
+ {
+ ext->seq.string = buf;
+ state = (get_funky_string (&buf, &p, false, &ext->seq.len)
+ ? 1 : -1);
+ }
+ else
+ state = -1;
+ /* XXX - recover here as with an unrecognized prefix? */
+ if (state == -1 && ext->ext.string)
+ _rl_errmsg ("LS_COLORS: syntax error: %s", ext->ext.string);
+ break;
+ }
+ }
+
+ if (state < 0)
+ {
+ COLOR_EXT_TYPE *e;
+ COLOR_EXT_TYPE *e2;
+
+ _rl_errmsg ("unparsable value for LS_COLORS environment variable");
+ free (color_buf);
+ for (e = _rl_color_ext_list; e != NULL; /* empty */)
+ {
+ e2 = e;
+ e = e->next;
+ free (e2);
+ }
+ _rl_color_ext_list = NULL;
+ _rl_colored_stats = 0; /* can't have colored stats without colors */
+ }
+#else /* !COLOR_SUPPORT */
+ ;
+#endif /* !COLOR_SUPPORT */
+}
diff --git a/lib/readline/parse-colors.h b/lib/readline/parse-colors.h
new file mode 100644
index 00000000..aef86f78
--- /dev/null
+++ b/lib/readline/parse-colors.h
@@ -0,0 +1,46 @@
+/* `dir', `vdir' and `ls' directory listing programs for GNU.
+
+ Modified by Chet Ramey for Readline.
+
+ Copyright (C) 1985, 1988, 1990-1991, 1995-2010, 2012 Free Software Foundation,
+ Inc.
+
+ 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 3 of the License, 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, see <http://www.gnu.org/licenses/>. */
+
+/* Written by Richard Stallman and David MacKenzie. */
+
+/* Color support by Peter Anvin <Peter.Anvin@linux.org> and Dennis
+ Flaherty <dennisf@denix.elk.miles.com> based on original patches by
+ Greg Lee <lee@uhunix.uhcc.hawaii.edu>. */
+
+#ifndef _PARSE_COLORS_H_
+#define _PARSE_COLORS_H_
+
+#include "readline.h"
+
+#define LEN_STR_PAIR(s) sizeof (s) - 1, s
+
+void _rl_parse_colors (void);
+
+static const char *const indicator_name[]=
+ {
+ "lc", "rc", "ec", "rs", "no", "fi", "di", "ln", "pi", "so",
+ "bd", "cd", "mi", "or", "ex", "do", "su", "sg", "st",
+ "ow", "tw", "ca", "mh", "cl", NULL
+ };
+
+/* Buffer for color sequences */
+static char *color_buf;
+
+#endif /* !_PARSE_COLORS_H_ */
diff --git a/lib/readline/posixdir.h b/lib/readline/posixdir.h
index bd33694d..0921c5d7 100644
--- a/lib/readline/posixdir.h
+++ b/lib/readline/posixdir.h
@@ -1,6 +1,6 @@
/* posixdir.h -- Posix directory reading includes and defines. */
-/* Copyright (C) 1987,1991 Free Software Foundation, Inc.
+/* Copyright (C) 1987,1991,2012 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -46,16 +46,26 @@
# define D_NAMLEN(d) ((d)->d_namlen)
#endif /* !HAVE_DIRENT_H */
+/* The bash code fairly consistenly uses d_fileno; make sure it's available */
#if defined (HAVE_STRUCT_DIRENT_D_INO) && !defined (HAVE_STRUCT_DIRENT_D_FILENO)
# define d_fileno d_ino
#endif
-#if defined (_POSIX_SOURCE) && (!defined (HAVE_STRUCT_DIRENT_D_INO) || defined (BROKEN_DIRENT_D_INO))
/* Posix does not require that the d_ino field be present, and some
systems do not provide it. */
+#if !defined (HAVE_STRUCT_DIRENT_D_INO) || defined (BROKEN_DIRENT_D_INO)
# define REAL_DIR_ENTRY(dp) 1
#else
# define REAL_DIR_ENTRY(dp) (dp->d_ino != 0)
#endif /* _POSIX_SOURCE */
+#if defined (HAVE_STRUCT_DIRENT_D_INO) && !defined (BROKEN_DIRENT_D_INO)
+# define D_INO_AVAILABLE
+#endif
+
+/* Signal the rest of the code that it can safely use dirent.d_fileno */
+#if defined (D_INO_AVAILABLE) || defined (HAVE_STRUCT_DIRENT_D_FILENO)
+# define D_FILENO_AVAILABLE 1
+#endif
+
#endif /* !_POSIXDIR_H_ */
diff --git a/lib/readline/posixjmp.h b/lib/readline/posixjmp.h
index 49bfecf3..98cf7185 100644
--- a/lib/readline/posixjmp.h
+++ b/lib/readline/posixjmp.h
@@ -30,11 +30,13 @@
# if !defined (__OPENNT)
# undef setjmp
# define setjmp(x) sigsetjmp((x), 1)
+# define setjmp_nosigs(x) sigsetjmp((x), 0)
# undef longjmp
# define longjmp(x, n) siglongjmp((x), (n))
# endif /* !__OPENNT */
#else
# define procenv_t jmp_buf
+# define setjmp_nosigs setjmp
#endif
#endif /* _POSIXJMP_H_ */
diff --git a/lib/readline/readline.c b/lib/readline/readline.c
index f2e4d933..03eefa6e 100644
--- a/lib/readline/readline.c
+++ b/lib/readline/readline.c
@@ -1,7 +1,7 @@
/* readline.c -- a general facility for reading lines of input
with emacs style editing and completion. */
-/* Copyright (C) 1987-2009 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2013 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.
@@ -82,6 +82,11 @@ extern int errno;
extern void _rl_free_history_entry PARAMS((HIST_ENTRY *));
+#if defined (COLOR_SUPPORT)
+extern void _rl_parse_colors PARAMS((void)); /* XXX */
+#endif
+
+
/* Forward declarations used in this file. */
static char *readline_internal PARAMS((void));
static void readline_initialize_everything PARAMS((void));
@@ -112,7 +117,6 @@ int rl_gnu_readline_p = 1;
By default, it is the standard emacs keymap. */
Keymap _rl_keymap = emacs_standard_keymap;
-
/* The current style of editing. */
int rl_editing_mode = emacs_mode;
@@ -238,13 +242,32 @@ int rl_erase_empty_line = 0;
character bound to accept-line. */
int rl_num_chars_to_read;
-/* Line buffer and maintenence. */
+/* Line buffer and maintenance. */
char *rl_line_buffer = (char *)NULL;
int rl_line_buffer_len = 0;
/* Key sequence `contexts' */
_rl_keyseq_cxt *_rl_kscxt = 0;
+int rl_executing_key;
+char *rl_executing_keyseq = 0;
+int _rl_executing_keyseq_size = 0;
+
+/* Timeout (specified in milliseconds) when reading characters making up an
+ ambiguous multiple-key sequence */
+int _rl_keyseq_timeout = 500;
+
+#define RESIZE_KEYSEQ_BUFFER() \
+ do \
+ { \
+ if (rl_key_sequence_length + 2 >= _rl_executing_keyseq_size) \
+ { \
+ _rl_executing_keyseq_size += 16; \
+ rl_executing_keyseq = xrealloc (rl_executing_keyseq, _rl_executing_keyseq_size); \
+ } \
+ } \
+ while (0);
+
/* Forward declarations used by the display, termcap, and history code. */
/* **************************************************************** */
@@ -279,6 +302,10 @@ int _rl_revert_all_at_newline = 0;
characters corresponding to keyboard-generated signals. */
int _rl_echo_control_chars = 1;
+/* Non-zero means to prefix the displayed prompt with a character indicating
+ the editing mode: @ for emacs, : for vi-command, + for vi-insert. */
+int _rl_show_mode_in_prompt = 0;
+
/* **************************************************************** */
/* */
/* Top Level Functions */
@@ -352,6 +379,11 @@ readline (prompt)
RL_SETSTATE (RL_STATE_CALLBACK);
#endif
+#if HAVE_DECL_AUDIT_TTY && defined (ENABLE_TTY_AUDIT_SUPPORT)
+ if (value)
+ _rl_audit_tty (value);
+#endif
+
return (value);
}
@@ -369,9 +401,19 @@ readline_internal_setup ()
_rl_in_stream = rl_instream;
_rl_out_stream = rl_outstream;
+ /* Enable the meta key only for the duration of readline(), if this
+ terminal has one and the terminal has been initialized */
+ if (_rl_enable_meta & RL_ISSTATE (RL_STATE_TERMPREPPED))
+ _rl_enable_meta_key ();
+
if (rl_startup_hook)
(*rl_startup_hook) ();
+#if defined (VI_MODE)
+ if (rl_editing_mode == vi_mode)
+ rl_vi_insertion_mode (1, 'i'); /* don't want to reset last */
+#endif /* VI_MODE */
+
/* If we're not echoing, we still want to at least print a prompt, because
rl_redisplay will not do it for us. If the calling application has a
custom redisplay function, though, let that function handle it. */
@@ -394,11 +436,6 @@ readline_internal_setup ()
(*rl_redisplay_function) ();
}
-#if defined (VI_MODE)
- if (rl_editing_mode == vi_mode)
- rl_vi_insert_mode (1, 'i');
-#endif /* VI_MODE */
-
if (rl_pre_input_hook)
(*rl_pre_input_hook) ();
@@ -437,6 +474,11 @@ readline_internal_teardown (eof)
if (rl_undo_list)
rl_free_undo_list ();
+ /* Disable the meta key, if this terminal has one and we were told to use it.
+ The check whether or not we sent the enable string is in
+ _rl_disable_meta_key(); the flag is set in _rl_enable_meta_key */
+ _rl_disable_meta_key ();
+
/* Restore normal cursor, if available. */
_rl_set_insert_mode (RL_IM_INSERT, 0);
@@ -492,7 +534,11 @@ readline_internal_charloop ()
#endif
lk = _rl_last_command_was_kill;
+#if defined (HAVE_POSIX_SIGSETJMP)
+ code = sigsetjmp (_rl_top_level, 0);
+#else
code = setjmp (_rl_top_level);
+#endif
if (code)
{
@@ -511,6 +557,7 @@ readline_internal_charloop ()
/* Then initialize the argument and number of keys read. */
_rl_reset_argument ();
rl_key_sequence_length = 0;
+ rl_executing_keyseq[0] = 0;
}
RL_SETSTATE(RL_STATE_READCMD);
@@ -519,7 +566,8 @@ readline_internal_charloop ()
/* look at input.c:rl_getc() for the circumstances under which this will
be returned; punt immediately on read error without converting it to
- a newline. */
+ a newline; assume that rl_read_key has already called the signal
+ handler. */
if (c == READERR)
{
#if defined (READLINE_CALLBACKS)
@@ -531,7 +579,9 @@ readline_internal_charloop ()
#endif
}
- /* EOF typed to a non-blank line is a <NL>. */
+ /* EOF typed to a non-blank line is a <NL>. If we want to change this,
+ to force any existing line to be ignored when read(2) reads EOF,
+ for example, this is the place to change. */
if (c == EOF && rl_end)
c = NEWLINE;
@@ -743,9 +793,10 @@ _rl_dispatch_subseq (key, map, got_subseq)
{
if (RL_ISSTATE (RL_STATE_MACRODEF))
_rl_add_macro_char (ESC);
+ RESIZE_KEYSEQ_BUFFER ();
+ rl_executing_keyseq[rl_key_sequence_length++] = ESC;
map = FUNCTION_TO_KEYMAP (map, ESC);
key = UNMETA (key);
- rl_key_sequence_length += 2;
return (_rl_dispatch (key, map));
}
else
@@ -765,13 +816,19 @@ _rl_dispatch_subseq (key, map, got_subseq)
{
/* Special case rl_do_lowercase_version (). */
if (func == rl_do_lowercase_version)
+ /* Should we do anything special if key == ANYOTHERKEY? */
return (_rl_dispatch (_rl_to_lower (key), map));
rl_executing_keymap = map;
+ rl_executing_key = key;
+
+ RESIZE_KEYSEQ_BUFFER();
+ rl_executing_keyseq[rl_key_sequence_length++] = key;
+ rl_executing_keyseq[rl_key_sequence_length] = '\0';
rl_dispatching = 1;
RL_SETSTATE(RL_STATE_DISPATCHING);
- (*map[key].function)(rl_numeric_arg * rl_arg_sign, key);
+ r = (*func) (rl_numeric_arg * rl_arg_sign, key);
RL_UNSETSTATE(RL_STATE_DISPATCHING);
rl_dispatching = 0;
@@ -788,7 +845,10 @@ _rl_dispatch_subseq (key, map, got_subseq)
/* OK, there's no function bound in this map, but there is a
shadow function that was overridden when the current keymap
was created. Return -2 to note that. */
- _rl_unget_char (key);
+ if (RL_ISSTATE (RL_STATE_MACROINPUT))
+ _rl_prev_macro_key ();
+ else
+ _rl_unget_char (key);
return -2;
}
else if (got_subseq)
@@ -797,7 +857,10 @@ _rl_dispatch_subseq (key, map, got_subseq)
have a matching key, nor was one overridden. This means
we need to back up the recursion chain and find the last
subsequence that is bound to a function. */
- _rl_unget_char (key);
+ if (RL_ISSTATE (RL_STATE_MACROINPUT))
+ _rl_prev_macro_key ();
+ else
+ _rl_unget_char (key);
return -1;
}
else
@@ -820,13 +883,17 @@ _rl_dispatch_subseq (key, map, got_subseq)
check whether there's input in the queue, which there generally
will be if an arrow key has been pressed, and, if there's not,
just dispatch to (what we assume is) rl_vi_movement_mode right
- away. This is essentially an input test with a zero timeout. */
+ away. This is essentially an input test with a zero timeout (by
+ default) or a timeout determined by the value of `keyseq-timeout' */
+ /* _rl_keyseq_timeout specified in milliseconds; _rl_input_queued
+ takes microseconds, so multiply by 1000 */
if (rl_editing_mode == vi_mode && key == ESC && map == vi_insertion_keymap
- && _rl_input_queued (0) == 0)
+ && _rl_input_queued ((_rl_keyseq_timeout > 0) ? _rl_keyseq_timeout*1000 : 0) == 0)
return (_rl_dispatch (ANYOTHERKEY, FUNCTION_TO_KEYMAP (map, key)));
#endif
- rl_key_sequence_length++;
+ RESIZE_KEYSEQ_BUFFER ();
+ rl_executing_keyseq[rl_key_sequence_length++] = key;
_rl_dispatching_keymap = FUNCTION_TO_KEYMAP (map, key);
/* Allocate new context here. Use linked contexts (linked through
@@ -855,6 +922,18 @@ _rl_dispatch_subseq (key, map, got_subseq)
}
#endif
+ /* Tentative inter-character timeout for potential multi-key
+ sequences? If no input within timeout, abort sequence and
+ act as if we got non-matching input. */
+ /* _rl_keyseq_timeout specified in milliseconds; _rl_input_queued
+ takes microseconds, so multiply by 1000 */
+ if (_rl_keyseq_timeout > 0 &&
+ (RL_ISSTATE (RL_STATE_INPUTPENDING|RL_STATE_MACROINPUT) == 0) &&
+ _rl_pushed_input_available () == 0 &&
+ _rl_dispatching_keymap[ANYOTHERKEY].function &&
+ _rl_input_queued (_rl_keyseq_timeout*1000) == 0)
+ return (_rl_subseq_result (-2, map, key, got_subseq));
+
newkey = _rl_subseq_getchar (key);
if (newkey < 0)
{
@@ -875,6 +954,7 @@ _rl_dispatch_subseq (key, map, got_subseq)
case ISMACR:
if (map[key].function != 0)
{
+ rl_executing_keyseq[rl_key_sequence_length] = '\0';
macro = savestring ((char *)map[key].function);
_rl_with_macro_input (macro);
return 0;
@@ -884,6 +964,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_key_sequence_length == 1 && /* XXX */
_rl_vi_textmod_command (key))
_rl_vi_set_last (key, rl_numeric_arg, rl_arg_sign);
#endif
@@ -935,14 +1016,20 @@ _rl_subseq_result (r, map, key, got_subseq)
/* We didn't match (r is probably -1), so return something to
tell the caller that it should try ANYOTHERKEY for an
overridden function. */
- _rl_unget_char (key);
+ if (RL_ISSTATE (RL_STATE_MACROINPUT))
+ _rl_prev_macro_key ();
+ else
+ _rl_unget_char (key);
_rl_dispatching_keymap = map;
return -2;
}
else if (r && got_subseq)
{
/* OK, back up the chain. */
- _rl_unget_char (key);
+ if (RL_ISSTATE (RL_STATE_MACROINPUT))
+ _rl_prev_macro_key ();
+ else
+ _rl_unget_char (key);
_rl_dispatching_keymap = map;
return -1;
}
@@ -971,7 +1058,7 @@ rl_initialize ()
RL_SETSTATE(RL_STATE_INITIALIZED);
}
- /* Initalize the current line information. */
+ /* Initialize the current line information. */
_rl_init_line_state ();
/* We aren't done yet. We haven't even gotten started yet! */
@@ -1091,14 +1178,19 @@ readline_initialize_everything ()
/* Try to bind a common arrow key prefix, if not already bound. */
bind_arrow_keys ();
- /* Enable the meta key, if this terminal has one. */
- if (_rl_enable_meta)
- _rl_enable_meta_key ();
-
/* 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 = (char *)rl_basic_word_break_characters;
+
+#if defined (COLOR_SUPPORT)
+ if (_rl_colored_stats)
+ _rl_parse_colors ();
+#endif
+
+ rl_executing_keyseq = malloc (_rl_executing_keyseq_size = 16);
+ if (rl_executing_keyseq)
+ rl_executing_keyseq[0] = '\0';
}
/* If this system allows us to look at the values of the regular
@@ -1159,6 +1251,20 @@ bind_arrow_keys_internal (map)
rl_bind_keyseq_if_unbound ("\340P", rl_get_next_history);
rl_bind_keyseq_if_unbound ("\340M", rl_forward_char);
rl_bind_keyseq_if_unbound ("\340K", rl_backward_char);
+ rl_bind_keyseq_if_unbound ("\340G", rl_beg_of_line);
+ rl_bind_keyseq_if_unbound ("\340O", rl_end_of_line);
+ rl_bind_keyseq_if_unbound ("\340S", rl_delete);
+ rl_bind_keyseq_if_unbound ("\340R", rl_overwrite_mode);
+
+ /* These may or may not work because of the embedded NUL. */
+ rl_bind_keyseq_if_unbound ("\\000H", rl_get_previous_history);
+ rl_bind_keyseq_if_unbound ("\\000P", rl_get_next_history);
+ rl_bind_keyseq_if_unbound ("\\000M", rl_forward_char);
+ rl_bind_keyseq_if_unbound ("\\000K", rl_backward_char);
+ rl_bind_keyseq_if_unbound ("\\000G", rl_beg_of_line);
+ rl_bind_keyseq_if_unbound ("\\000O", rl_end_of_line);
+ rl_bind_keyseq_if_unbound ("\\000S", rl_delete);
+ rl_bind_keyseq_if_unbound ("\\000R", rl_overwrite_mode);
#endif
_rl_keymap = xkeymap;
diff --git a/lib/readline/readline.h b/lib/readline/readline.h
index 0de168cd..08dcd2be 100644
--- a/lib/readline/readline.h
+++ b/lib/readline/readline.h
@@ -1,6 +1,6 @@
/* Readline.h -- the names of functions callable from within readline. */
-/* Copyright (C) 1987-2011 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2013 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.
@@ -39,9 +39,9 @@ extern "C" {
#endif
/* Hex-encoded Readline version number. */
-#define RL_READLINE_VERSION 0x0602 /* Readline 6.2 */
+#define RL_READLINE_VERSION 0x0603 /* Readline 6.3 */
#define RL_VERSION_MAJOR 6
-#define RL_VERSION_MINOR 2
+#define RL_VERSION_MINOR 3
/* Readline data structures. */
@@ -185,6 +185,7 @@ extern int rl_forward_search_history PARAMS((int, int));
extern int rl_start_kbd_macro PARAMS((int, int));
extern int rl_end_kbd_macro PARAMS((int, int));
extern int rl_call_last_kbd_macro PARAMS((int, int));
+extern int rl_print_last_kbd_macro PARAMS((int, int));
/* Bindable undo commands. */
extern int rl_revert_line PARAMS((int, int));
@@ -204,6 +205,8 @@ extern int rl_tty_status PARAMS((int, int));
/* Bindable commands for incremental and non-incremental history searching. */
extern int rl_history_search_forward PARAMS((int, int));
extern int rl_history_search_backward PARAMS((int, int));
+extern int rl_history_substr_search_forward PARAMS((int, int));
+extern int rl_history_substr_search_backward PARAMS((int, int));
extern int rl_noninc_forward_search PARAMS((int, int));
extern int rl_noninc_reverse_search PARAMS((int, int));
extern int rl_noninc_forward_search_again PARAMS((int, int));
@@ -339,6 +342,7 @@ extern Keymap rl_make_bare_keymap PARAMS((void));
extern Keymap rl_copy_keymap PARAMS((Keymap));
extern Keymap rl_make_keymap PARAMS((void));
extern void rl_discard_keymap PARAMS((Keymap));
+extern void rl_free_keymap PARAMS((Keymap));
extern Keymap rl_get_keymap_by_name PARAMS((const char *));
extern char *rl_get_keymap_name PARAMS((Keymap));
@@ -436,6 +440,10 @@ extern void rl_echo_signal_char PARAMS((int));
extern int rl_set_paren_blink_timeout PARAMS((int));
+/* History management functions. */
+
+extern void rl_clear_history PARAMS((void));
+
/* Undocumented. */
extern int rl_maybe_save_line PARAMS((void));
extern int rl_maybe_unsave_line PARAMS((void));
@@ -560,6 +568,13 @@ extern rl_hook_func_t *rl_pre_input_hook;
awaiting character input, or NULL, for no event handling. */
extern rl_hook_func_t *rl_event_hook;
+/* The address of a function to call if a read is interrupted by a signal. */
+extern rl_hook_func_t *rl_signal_event_hook;
+
+/* The address of a function to call if Readline needs to know whether or not
+ there is data available from the current input source. */
+extern rl_hook_func_t *rl_input_available_hook;
+
/* The address of the function to call to fetch a character from the current
Readline input stream */
extern rl_getc_func_t *rl_getc_function;
@@ -573,6 +588,10 @@ extern rl_voidfunc_t *rl_deprep_term_function;
extern Keymap rl_executing_keymap;
extern Keymap rl_binding_keymap;
+extern int rl_executing_key;
+extern char *rl_executing_keyseq;
+extern int rl_key_sequence_length;
+
/* Display variables. */
/* If non-zero, readline will erase the entire line, including any prompt,
if the only thing typed on an otherwise-blank line is something bound to
@@ -603,6 +622,10 @@ extern int rl_catch_signals;
to do that. */
extern int rl_catch_sigwinch;
+/* If non-zero, the readline SIGWINCH handler will modify LINES and
+ COLUMNS in the environment. */
+extern int rl_change_environment;
+
/* Completion variables. */
/* Pointer to the generator function for completion_matches ().
NULL means to use rl_filename_completion_function (), the default
@@ -686,6 +709,13 @@ extern rl_icppfunc_t *rl_directory_completion_hook;
it in bash to see how well it goes. */
extern rl_icppfunc_t *rl_directory_rewrite_hook;
+/* If non-zero, this is the address of a function for the completer to call
+ before deciding which character to append to a completed name. It should
+ modify the directory name passed as an argument if appropriate, and return
+ non-zero if it modifies the name. This should not worry about dequoting
+ the filename; that has already happened by the time it gets here. */
+extern rl_icppfunc_t *rl_filename_stat_hook;
+
/* If non-zero, this is the address of a function to call when reading
directory entries from the filesystem for completion and comparing
them to the partial word to be completed. The function should
diff --git a/lib/readline/rlconf.h b/lib/readline/rlconf.h
index 39f94dbc..1a40afce 100644
--- a/lib/readline/rlconf.h
+++ b/lib/readline/rlconf.h
@@ -1,6 +1,6 @@
/* rlconf.h -- readline configuration definitions */
-/* Copyright (C) 1992-2009 Free Software Foundation, Inc.
+/* Copyright (C) 1992-2012 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.
@@ -28,8 +28,12 @@
/* Define this to get an indication of file type when listing completions. */
#define VISIBLE_STATS
+/* Define this to get support for colors when listing completions and in
+ other places. */
+#define COLOR_SUPPORT
+
/* This definition is needed by readline.c, rltty.c, and signals.c. */
-/* If on, then readline handles signals in a way that doesn't screw. */
+/* If on, then readline handles signals in a way that doesn't suck. */
#define HANDLE_SIGNALS
/* Ugly but working hack for binding prefix meta. */
@@ -58,4 +62,8 @@
/* Define this if you want the cursor to indicate insert or overwrite mode. */
/* #define CURSOR_MODE */
+/* Define this if you want to enable code that talks to the Linux kernel
+ tty auditing system. */
+#define ENABLE_TTY_AUDIT_SUPPORT
+
#endif /* _RLCONF_H_ */
diff --git a/lib/readline/rldefs.h b/lib/readline/rldefs.h
index 02577546..dab1beba 100644
--- a/lib/readline/rldefs.h
+++ b/lib/readline/rldefs.h
@@ -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.
@@ -79,8 +79,8 @@ extern char *strchr (), *strrchr ();
#define _rl_stricmp strcasecmp
#define _rl_strnicmp strncasecmp
#else
-extern int _rl_stricmp PARAMS((char *, char *));
-extern int _rl_strnicmp PARAMS((char *, char *, int));
+extern int _rl_stricmp PARAMS((const char *, const char *));
+extern int _rl_strnicmp PARAMS((const char *, const char *, int));
#endif
#if defined (HAVE_STRPBRK) && !defined (HAVE_MULTIBYTE)
@@ -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
diff --git a/lib/readline/rlmbutil.h b/lib/readline/rlmbutil.h
index 7716a70c..06d85ab3 100644
--- a/lib/readline/rlmbutil.h
+++ b/lib/readline/rlmbutil.h
@@ -123,6 +123,15 @@ extern int _rl_walphabetic PARAMS((wchar_t));
#define MB_INVALIDCH(x) ((x) == (size_t)-1 || (x) == (size_t)-2)
#define MB_NULLWCH(x) ((x) == 0)
+/* Unicode combining characters range from U+0300 to U+036F */
+#define UNICODE_COMBINING_CHAR(x) ((x) >= 768 && (x) <= 879)
+
+#if defined (WCWIDTH_BROKEN)
+# define WCWIDTH(wc) ((_rl_utf8locale && UNICODE_COMBINING_CHAR(wc)) ? 0 : wcwidth(wc))
+#else
+# define WCWIDTH(wc) wcwidth(wc)
+#endif
+
#else /* !HANDLE_MULTIBYTE */
#undef MB_LEN_MAX
diff --git a/lib/readline/rlprivate.h b/lib/readline/rlprivate.h
index 384ff67c..14a370d2 100644
--- a/lib/readline/rlprivate.h
+++ b/lib/readline/rlprivate.h
@@ -1,7 +1,7 @@
/* rlprivate.h -- functions and variables global to the readline library,
but not intended for use by applications. */
-/* Copyright (C) 1999-2010 Free Software Foundation, Inc.
+/* Copyright (C) 1999-2012 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.
@@ -42,6 +42,12 @@
if (_rl_caught_signal) _rl_signal_handler (_rl_caught_signal); \
} while (0)
+#define RL_SIG_RECEIVED() (_rl_caught_signal != 0)
+#define RL_SIGINT_RECEIVED() (_rl_caught_signal == SIGINT)
+
+#define CUSTOM_REDISPLAY_FUNC() (rl_redisplay_function != rl_redisplay)
+#define CUSTOM_INPUT_FUNC() (rl_getc_function != rl_getc)
+
/*************************************************************************
* *
* Global structs undocumented in texinfo manual and not in readline.h *
@@ -86,9 +92,11 @@ typedef struct __rl_search_context
int history_pos;
int direction;
+ int prevc;
int lastc;
#if defined (HANDLE_MULTIBYTE)
char mb[MB_LEN_MAX];
+ char pmb[MB_LEN_MAX];
#endif
char *sline;
@@ -156,6 +164,8 @@ typedef struct __rl_callback_generic_arg
typedef int _rl_callback_func_t PARAMS((_rl_callback_generic_arg *));
+typedef void _rl_sigcleanup_func_t PARAMS((int, void *));
+
/*************************************************************************
* *
* Global functions undocumented in texinfo manual and not in readline.h *
@@ -173,12 +183,14 @@ extern int rl_complete_with_tilde_expansion;
#if defined (VISIBLE_STATS)
extern int rl_visible_stats;
#endif /* VISIBLE_STATS */
+#if defined (COLOR_SUPPORT)
+extern int _rl_colored_stats;
+#endif
/* readline.c */
extern int rl_line_buffer_len;
extern int rl_arg_sign;
extern int rl_visible_prompt_length;
-extern int rl_key_sequence_length;
extern int rl_byte_oriented;
/* display.c */
@@ -189,7 +201,7 @@ extern int rl_blink_matching_paren;
/*************************************************************************
* *
- * Global functions and variables unsed and undocumented *
+ * Global functions and variables unused and undocumented *
* *
*************************************************************************/
@@ -240,6 +252,7 @@ extern void _rl_callback_data_dispose PARAMS((_rl_callback_generic_arg *));
#endif /* READLINE_CALLBACKS */
/* bind.c */
+extern char *_rl_untranslate_macro_value PARAMS((char *, int));
/* complete.c */
extern void _rl_reset_completion_state PARAMS((void));
@@ -248,6 +261,7 @@ extern void _rl_free_match_list PARAMS((char **));
/* display.c */
extern char *_rl_strip_prompt PARAMS((char *));
+extern void _rl_reset_prompt PARAMS((void));
extern void _rl_move_cursor_relative PARAMS((int, const char *));
extern void _rl_move_vert PARAMS((int));
extern void _rl_save_prompt PARAMS((void));
@@ -282,6 +296,7 @@ extern int _rl_search_getchar PARAMS((_rl_search_cxt *));
/* macro.c */
extern void _rl_with_macro_input PARAMS((char *));
extern int _rl_next_macro_key PARAMS((void));
+extern int _rl_prev_macro_key PARAMS((void));
extern void _rl_push_executing_macro PARAMS((void));
extern void _rl_pop_executing_macro PARAMS((void));
extern void _rl_add_macro_char PARAMS((int));
@@ -330,6 +345,7 @@ extern void _rl_release_sigwinch PARAMS((void));
/* terminal.c */
extern void _rl_get_screen_size PARAMS((int, int));
+extern void _rl_sigwinch_resize_terminal PARAMS((void));
extern int _rl_init_terminal_io PARAMS((const char *));
#ifdef _MINIX
extern void _rl_output_character_function PARAMS((int));
@@ -339,6 +355,7 @@ extern int _rl_output_character_function PARAMS((int));
extern void _rl_output_some_chars PARAMS((const char *, int));
extern int _rl_backspace PARAMS((int));
extern void _rl_enable_meta_key PARAMS((void));
+extern void _rl_disable_meta_key PARAMS((void));
extern void _rl_control_keypad PARAMS((int));
extern void _rl_set_cursor PARAMS((int, int));
@@ -360,6 +377,7 @@ extern int _rl_set_mark_at_pos PARAMS((int));
/* undo.c */
extern UNDO_LIST *_rl_copy_undo_entry PARAMS((UNDO_LIST *));
extern UNDO_LIST *_rl_copy_undo_list PARAMS((UNDO_LIST *));
+extern void _rl_free_undo_list PARAMS((UNDO_LIST *));
/* util.c */
#if defined (USE_VARARGS) && defined (PREFER_STDARG)
@@ -371,6 +389,7 @@ extern void _rl_ttymsg ();
extern void _rl_errmsg ();
extern void _rl_trace ();
#endif
+extern void _rl_audit_tty PARAMS((char *));
extern int _rl_tropen PARAMS((void));
@@ -441,6 +460,9 @@ extern int _rl_history_saved_point;
extern _rl_arg_cxt _rl_argcxt;
+/* nls.c */
+extern int _rl_utf8locale;
+
/* readline.c */
extern int _rl_echoing_p;
extern int _rl_horizontal_scroll_mode;
@@ -452,6 +474,7 @@ extern int _rl_output_meta_chars;
extern int _rl_bind_stty_chars;
extern int _rl_revert_all_at_newline;
extern int _rl_echo_control_chars;
+extern int _rl_show_mode_in_prompt;
extern char *_rl_comment_begin;
extern unsigned char _rl_parsing_conditionalized_out;
extern Keymap _rl_keymap;
@@ -461,6 +484,9 @@ extern int _rl_last_command_was_kill;
extern int _rl_eof_char;
extern procenv_t _rl_top_level;
extern _rl_keyseq_cxt *_rl_kscxt;
+extern int _rl_keyseq_timeout;
+
+extern int _rl_executing_keyseq_size;
/* search.c */
extern _rl_search_cxt *_rl_nscxt;
@@ -469,6 +495,9 @@ extern _rl_search_cxt *_rl_nscxt;
extern int _rl_interrupt_immediately;
extern int volatile _rl_caught_signal;
+extern _rl_sigcleanup_func_t *_rl_sigcleanup;
+extern void *_rl_sigcleanarg;
+
extern int _rl_echoctl;
extern int _rl_intr_char;
diff --git a/lib/readline/rlstdc.h b/lib/readline/rlstdc.h
index a6d23942..2aaa30ba 100644
--- a/lib/readline/rlstdc.h
+++ b/lib/readline/rlstdc.h
@@ -42,4 +42,16 @@
# endif
#endif
+/* Moved from config.h.in because readline.h:rl_message depends on these
+ defines. */
+#if defined (__STDC__) && defined (HAVE_STDARG_H)
+# define PREFER_STDARG
+# define USE_VARARGS
+#else
+# if defined (HAVE_VARARGS_H)
+# define PREFER_VARARGS
+# define USE_VARARGS
+# endif
+#endif
+
#endif /* !_RL_STDC_H_ */
diff --git a/lib/readline/rltty.c b/lib/readline/rltty.c
index d237b1c0..908bae18 100644
--- a/lib/readline/rltty.c
+++ b/lib/readline/rltty.c
@@ -121,7 +121,7 @@ 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 set_special_char PARAMS((Keymap, TIOTYPE *, int, rl_command_func_t *));
static void
save_tty_chars (tiop)
@@ -341,7 +341,7 @@ 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 set_special_char PARAMS((Keymap, TIOTYPE *, int, rl_command_func_t *));
static void _rl_bind_tty_special_chars PARAMS((Keymap, TIOTYPE));
#if defined (FLUSHO)
@@ -528,10 +528,10 @@ prepare_terminal_settings (meta_flag, oldtio, tiop)
#if defined (USE_XON_XOFF)
#if defined (IXANY)
- tiop->c_iflag &= ~(IXON | IXOFF | IXANY);
+ tiop->c_iflag &= ~(IXON | IXANY);
#else
/* `strict' Posix systems do not define IXANY. */
- tiop->c_iflag &= ~(IXON | IXOFF);
+ tiop->c_iflag &= ~IXON;
#endif /* IXANY */
#endif /* USE_XON_XOFF */
@@ -678,7 +678,7 @@ rl_deprep_terminal ()
/* Try to keep this function from being interrupted. */
_rl_block_sigint ();
- tty = rl_instream ? fileno (rl_instream) : fileno (stdout);
+ tty = rl_instream ? fileno (rl_instream) : fileno (stdin);
if (_rl_enable_keypad)
_rl_control_keypad (0);
diff --git a/lib/readline/rltypedefs.h b/lib/readline/rltypedefs.h
index 60f29a18..b113ee6e 100644
--- a/lib/readline/rltypedefs.h
+++ b/lib/readline/rltypedefs.h
@@ -1,6 +1,6 @@
/* rltypedefs.h -- Type declarations for readline functions. */
-/* Copyright (C) 2000-2009 Free Software Foundation, Inc.
+/* Copyright (C) 2000-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.
@@ -26,18 +26,6 @@
extern "C" {
#endif
-/* Old-style */
-
-#if !defined (_FUNCTION_DEF)
-# define _FUNCTION_DEF
-
-typedef int Function ();
-typedef void VFunction ();
-typedef char *CPFunction ();
-typedef char **CPPFunction ();
-
-#endif /* _FUNCTION_DEF */
-
/* New style. */
#if !defined (_RL_FUNCTION_TYPEDEF)
diff --git a/lib/readline/search.c b/lib/readline/search.c
index 04468fc4..028c2505 100644
--- a/lib/readline/search.c
+++ b/lib/readline/search.c
@@ -1,6 +1,6 @@
/* search.c - code for non-incremental searching in emacs and vi modes. */
-/* Copyright (C) 1992-2009 Free Software Foundation, Inc.
+/* Copyright (C) 1992-2013 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.
@@ -43,6 +43,7 @@
#include "readline.h"
#include "history.h"
+#include "histlib.h"
#include "rlprivate.h"
#include "xmalloc.h"
@@ -66,6 +67,8 @@ static char *prev_line_found = (char *) NULL;
static int rl_history_search_len;
static int rl_history_search_pos;
+static int rl_history_search_flags;
+
static char *history_search_string;
static int history_string_size;
@@ -74,7 +77,7 @@ static int noninc_search_from_pos PARAMS((char *, int, int));
static int noninc_dosearch PARAMS((char *, int));
static int noninc_search PARAMS((int, int));
static int rl_history_search_internal PARAMS((int, int));
-static void rl_history_search_reinit PARAMS((void));
+static void rl_history_search_reinit PARAMS((int));
static _rl_search_cxt *_rl_nsearch_init PARAMS((int, int));
static int _rl_nsearch_cleanup PARAMS((_rl_search_cxt *, int));
@@ -169,7 +172,8 @@ noninc_dosearch (string, dir)
oldpos = where_history ();
history_set_pos (noninc_history_pos);
- entry = current_history ();
+ entry = current_history (); /* will never be NULL after successful search */
+
#if defined (VI_MODE)
if (rl_editing_mode != vi_mode)
#endif
@@ -210,7 +214,7 @@ _rl_nsearch_init (dir, pchar)
rl_end = rl_point = 0;
p = _rl_make_prompt_for_search (pchar ? pchar : ':');
- rl_message ("%s", p, 0);
+ rl_message ("%s", p);
xfree (p);
RL_SETSTATE(RL_STATE_NSEARCH);
@@ -453,15 +457,19 @@ rl_history_search_internal (count, dir)
{
HIST_ENTRY *temp;
int ret, oldpos;
+ char *t;
rl_maybe_save_line ();
temp = (HIST_ENTRY *)NULL;
- /* Search COUNT times through the history for a line whose prefix
- matches history_search_string. When this loop finishes, TEMP,
- if non-null, is the history line to copy into the line buffer. */
+ /* Search COUNT times through the history for a line matching
+ history_search_string. If history_search_string[0] == '^', the
+ line must match from the start; otherwise any substring can match.
+ When this loop finishes, TEMP, if non-null, is the history line to
+ copy into the line buffer. */
while (count)
{
+ RL_CHECK_SIGNALS ();
ret = noninc_search_from_pos (history_search_string, rl_history_search_pos + dir, dir);
if (ret == -1)
break;
@@ -470,7 +478,7 @@ rl_history_search_internal (count, dir)
rl_history_search_pos = ret;
oldpos = where_history ();
history_set_pos (rl_history_search_pos);
- temp = current_history ();
+ temp = current_history (); /* will never be NULL after successful search */
history_set_pos (oldpos);
/* Don't find multiple instances of the same line. */
@@ -505,35 +513,49 @@ rl_history_search_internal (count, dir)
/* Copy the line we found into the current line buffer. */
make_history_line_current (temp);
- rl_point = rl_history_search_len;
+ if (rl_history_search_flags & ANCHORED_SEARCH)
+ rl_point = rl_history_search_len; /* easy case */
+ else
+ {
+ t = strstr (rl_line_buffer, history_search_string);
+ rl_point = t ? (int)(t - rl_line_buffer) + rl_history_search_len : rl_end;
+ }
rl_mark = rl_end;
return 0;
}
static void
-rl_history_search_reinit ()
+rl_history_search_reinit (flags)
+ int flags;
{
+ int sind;
+
rl_history_search_pos = where_history ();
rl_history_search_len = rl_point;
+ rl_history_search_flags = flags;
+
prev_line_found = (char *)NULL;
if (rl_point)
{
+ /* Allocate enough space for anchored and non-anchored searches */
if (rl_history_search_len >= history_string_size - 2)
{
history_string_size = rl_history_search_len + 2;
history_search_string = (char *)xrealloc (history_search_string, history_string_size);
}
- history_search_string[0] = '^';
- strncpy (history_search_string + 1, rl_line_buffer, rl_point);
- history_search_string[rl_point + 1] = '\0';
+ sind = 0;
+ if (flags & ANCHORED_SEARCH)
+ history_search_string[sind++] = '^';
+ strncpy (history_search_string + sind, rl_line_buffer, rl_point);
+ history_search_string[rl_point + sind] = '\0';
}
_rl_free_saved_history_line ();
}
/* Search forward in the history for the string of characters
from the start of the line to rl_point. This is a non-incremental
- search. */
+ search. The search is anchored to the beginning of the history line. */
int
rl_history_search_forward (count, ignore)
int count, ignore;
@@ -543,7 +565,7 @@ rl_history_search_forward (count, ignore)
if (rl_last_func != rl_history_search_forward &&
rl_last_func != rl_history_search_backward)
- rl_history_search_reinit ();
+ rl_history_search_reinit (ANCHORED_SEARCH);
if (rl_history_search_len == 0)
return (rl_get_next_history (count, ignore));
@@ -562,7 +584,46 @@ rl_history_search_backward (count, ignore)
if (rl_last_func != rl_history_search_forward &&
rl_last_func != rl_history_search_backward)
- rl_history_search_reinit ();
+ rl_history_search_reinit (ANCHORED_SEARCH);
+
+ if (rl_history_search_len == 0)
+ return (rl_get_previous_history (count, ignore));
+ return (rl_history_search_internal (abs (count), (count > 0) ? -1 : 1));
+}
+
+/* Search forward in the history for the string of characters
+ from the start of the line to rl_point. This is a non-incremental
+ search. The search succeeds if the search string is present anywhere
+ in the history line. */
+int
+rl_history_substr_search_forward (count, ignore)
+ int count, ignore;
+{
+ if (count == 0)
+ return (0);
+
+ if (rl_last_func != rl_history_substr_search_forward &&
+ rl_last_func != rl_history_substr_search_backward)
+ rl_history_search_reinit (NON_ANCHORED_SEARCH);
+
+ if (rl_history_search_len == 0)
+ return (rl_get_next_history (count, ignore));
+ return (rl_history_search_internal (abs (count), (count > 0) ? 1 : -1));
+}
+
+/* Search backward through the history for the string of characters
+ from the start of the line to rl_point. This is a non-incremental
+ search. */
+int
+rl_history_substr_search_backward (count, ignore)
+ int count, ignore;
+{
+ if (count == 0)
+ return (0);
+
+ if (rl_last_func != rl_history_substr_search_forward &&
+ rl_last_func != rl_history_substr_search_backward)
+ rl_history_search_reinit (NON_ANCHORED_SEARCH);
if (rl_history_search_len == 0)
return (rl_get_previous_history (count, ignore));
diff --git a/lib/readline/shell.c b/lib/readline/shell.c
index ac0fb360..6947295e 100644
--- a/lib/readline/shell.c
+++ b/lib/readline/shell.c
@@ -59,6 +59,8 @@
#include "rlstdc.h"
#include "rlshell.h"
+#include "rldefs.h"
+
#include "xmalloc.h"
#if defined (HAVE_GETPWUID) && !defined (HAVE_GETPW_DECLS)
@@ -120,31 +122,27 @@ sh_single_quote (string)
/* Set the environment variables LINES and COLUMNS to lines and cols,
respectively. */
+static char setenv_buf[INT_STRLEN_BOUND (int) + 1];
+static char putenv_buf1[INT_STRLEN_BOUND (int) + 6 + 1]; /* sizeof("LINES=") == 6 */
+static char putenv_buf2[INT_STRLEN_BOUND (int) + 8 + 1]; /* sizeof("COLUMNS=") == 8 */
+
void
sh_set_lines_and_columns (lines, cols)
int lines, cols;
{
- char *b;
-
#if defined (HAVE_SETENV)
- b = (char *)xmalloc (INT_STRLEN_BOUND (int) + 1);
- sprintf (b, "%d", lines);
- setenv ("LINES", b, 1);
- xfree (b);
-
- b = (char *)xmalloc (INT_STRLEN_BOUND (int) + 1);
- sprintf (b, "%d", cols);
- setenv ("COLUMNS", b, 1);
- xfree (b);
+ sprintf (setenv_buf, "%d", lines);
+ setenv ("LINES", setenv_buf, 1);
+
+ sprintf (setenv_buf, "%d", cols);
+ setenv ("COLUMNS", setenv_buf, 1);
#else /* !HAVE_SETENV */
# if defined (HAVE_PUTENV)
- b = (char *)xmalloc (INT_STRLEN_BOUND (int) + sizeof ("LINES=") + 1);
- sprintf (b, "LINES=%d", lines);
- putenv (b);
+ sprintf (putenv_buf1, "LINES=%d", lines);
+ putenv (putenv_buf1);
- b = (char *)xmalloc (INT_STRLEN_BOUND (int) + sizeof ("COLUMNS=") + 1);
- sprintf (b, "COLUMNS=%d", cols);
- putenv (b);
+ sprintf (putenv_buf2, "COLUMNS=%d", cols);
+ putenv (putenv_buf2);
# endif /* HAVE_PUTENV */
#endif /* !HAVE_SETENV */
}
@@ -159,15 +157,27 @@ sh_get_env_value (varname)
char *
sh_get_home_dir ()
{
- char *home_dir;
+ static char *home_dir = (char *)NULL;
struct passwd *entry;
+ if (home_dir)
+ return (home_dir);
+
home_dir = (char *)NULL;
#if defined (HAVE_GETPWUID)
+# if defined (__TANDEM)
+ entry = getpwnam (getlogin ());
+# else
entry = getpwuid (getuid ());
+# endif
if (entry)
- home_dir = entry->pw_dir;
+ home_dir = savestring (entry->pw_dir);
+#endif
+
+#if defined (HAVE_GETPWENT)
+ endpwent (); /* some systems need this */
#endif
+
return (home_dir);
}
diff --git a/lib/readline/signals.c b/lib/readline/signals.c
index 6a68d78c..61f02f9f 100644
--- a/lib/readline/signals.c
+++ b/lib/readline/signals.c
@@ -1,6 +1,6 @@
/* signals.c -- signal handling support for readline. */
-/* 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.
@@ -80,6 +80,7 @@ typedef struct { SigHandler *sa_handler; int sa_mask, sa_flags; } sighandler_cxt
static SigHandler *rl_set_sighandler PARAMS((int, SigHandler *, sighandler_cxt *));
static void rl_maybe_set_sighandler PARAMS((int, SigHandler *, sighandler_cxt *));
+static void rl_maybe_restore_sighandler PARAMS((int, sighandler_cxt *));
static RETSIGTYPE rl_signal_handler PARAMS((int));
static RETSIGTYPE _rl_handle_signal PARAMS((int));
@@ -87,7 +88,7 @@ static RETSIGTYPE _rl_handle_signal PARAMS((int));
/* Exported variables for use by applications. */
/* If non-zero, readline will install its own signal handlers for
- SIGINT, SIGTERM, SIGQUIT, SIGALRM, SIGTSTP, SIGTTIN, and SIGTTOU. */
+ SIGINT, SIGTERM, SIGHUP, SIGQUIT, SIGALRM, SIGTSTP, SIGTTIN, and SIGTTOU. */
int rl_catch_signals = 1;
/* If non-zero, readline will install a signal handler for SIGWINCH. */
@@ -118,7 +119,7 @@ static int sigwinch_set_flag;
/* */
/* **************************************************************** */
-static sighandler_cxt old_int, old_term, old_alrm, old_quit;
+static sighandler_cxt old_int, old_term, old_hup, old_alrm, old_quit;
#if defined (SIGTSTP)
static sighandler_cxt old_tstp, old_ttou, old_ttin;
#endif
@@ -126,6 +127,9 @@ static sighandler_cxt old_tstp, old_ttou, old_ttin;
static sighandler_cxt old_winch;
#endif
+_rl_sigcleanup_func_t *_rl_sigcleanup;
+void *_rl_sigcleanarg;
+
/* Readline signal handler functions. */
/* Called from RL_CHECK_SIGNALS() macro */
@@ -135,7 +139,21 @@ _rl_signal_handler (sig)
{
_rl_caught_signal = 0; /* XXX */
- _rl_handle_signal (sig);
+#if defined (SIGWINCH)
+ if (sig == SIGWINCH)
+ {
+ rl_resize_terminal ();
+ /* XXX - experimental for now */
+ /* Call a signal hook because though we called the original signal handler
+ in rl_sigwinch_handler below, we will not resend the signal to
+ ourselves. */
+ if (rl_signal_event_hook)
+ (*rl_signal_event_hook) ();
+ }
+ else
+#endif
+ _rl_handle_signal (sig);
+
SIGHANDLER_RETURN;
}
@@ -143,7 +161,7 @@ static RETSIGTYPE
rl_signal_handler (sig)
int sig;
{
- if (_rl_interrupt_immediately || RL_ISSTATE(RL_STATE_CALLBACK))
+ if (_rl_interrupt_immediately)
{
_rl_interrupt_immediately = 0;
_rl_handle_signal (sig);
@@ -181,6 +199,15 @@ _rl_handle_signal (sig)
rl_set_sighandler (sig, SIG_IGN, &dummy_cxt);
#endif /* !HAVE_BSD_SIGNALS && !HAVE_POSIX_SIGNALS */
+ /* If there's a sig cleanup function registered, call it and `deregister'
+ the cleanup function to avoid multiple calls */
+ if (_rl_sigcleanup)
+ {
+ (*_rl_sigcleanup) (sig, _rl_sigcleanarg);
+ _rl_sigcleanup = 0;
+ _rl_sigcleanarg = 0;
+ }
+
switch (sig)
{
case SIGINT:
@@ -189,6 +216,7 @@ _rl_handle_signal (sig)
/* FALLTHROUGH */
case SIGTERM:
+ case SIGHUP:
#if defined (SIGTSTP)
case SIGTSTP:
case SIGTTOU:
@@ -232,7 +260,7 @@ _rl_handle_signal (sig)
# endif /* HAVE_BSD_SIGNALS */
#endif /* !HAVE_POSIX_SIGNALS */
- rl_reset_after_signal ();
+ rl_reset_after_signal ();
}
RL_UNSETSTATE(RL_STATE_SIGHANDLER);
@@ -257,7 +285,7 @@ rl_sigwinch_handler (sig)
#endif
RL_SETSTATE(RL_STATE_SIGHANDLER);
- rl_resize_terminal ();
+ _rl_caught_signal = sig;
/* If another sigwinch handler has been installed, call it. */
oh = (SigHandler *)old_winch.sa_handler;
@@ -317,6 +345,8 @@ rl_set_sighandler (sig, handler, ohandler)
return (ohandler->sa_handler);
}
+/* Set disposition of SIG to HANDLER, returning old state in OHANDLER. Don't
+ change disposition if OHANDLER indicates the signal was ignored. */
static void
rl_maybe_set_sighandler (sig, handler, ohandler)
int sig;
@@ -327,11 +357,29 @@ rl_maybe_set_sighandler (sig, handler, ohandler)
SigHandler *oh;
sigemptyset (&dummy.sa_mask);
+ dummy.sa_flags = 0;
oh = rl_set_sighandler (sig, handler, ohandler);
if (oh == (SigHandler *)SIG_IGN)
rl_sigaction (sig, ohandler, &dummy);
}
+/* Set the disposition of SIG to HANDLER, if HANDLER->sa_handler indicates the
+ signal was not being ignored. MUST only be called for signals whose
+ disposition was changed using rl_maybe_set_sighandler or for which the
+ SIG_IGN check was performed inline (e.g., SIGALRM below). */
+static void
+rl_maybe_restore_sighandler (sig, handler)
+ int sig;
+ sighandler_cxt *handler;
+{
+ sighandler_cxt dummy;
+
+ sigemptyset (&dummy.sa_mask);
+ dummy.sa_flags = 0;
+ if (handler->sa_handler != SIG_IGN)
+ rl_sigaction (sig, handler, &dummy);
+}
+
int
rl_set_signals ()
{
@@ -349,6 +397,7 @@ rl_set_signals ()
sigaddset (&bset, SIGINT);
sigaddset (&bset, SIGTERM);
+ sigaddset (&bset, SIGHUP);
#if defined (SIGQUIT)
sigaddset (&bset, SIGQUIT);
#endif
@@ -377,6 +426,7 @@ rl_set_signals ()
rl_maybe_set_sighandler (SIGINT, rl_signal_handler, &old_int);
rl_maybe_set_sighandler (SIGTERM, rl_signal_handler, &old_term);
+ rl_maybe_set_sighandler (SIGHUP, rl_signal_handler, &old_hup);
#if defined (SIGQUIT)
rl_maybe_set_sighandler (SIGQUIT, rl_signal_handler, &old_quit);
#endif
@@ -434,25 +484,31 @@ rl_clear_signals ()
{
sigemptyset (&dummy.sa_mask);
- rl_sigaction (SIGINT, &old_int, &dummy);
- rl_sigaction (SIGTERM, &old_term, &dummy);
+ /* Since rl_maybe_set_sighandler doesn't override a SIG_IGN handler,
+ we should in theory not have to restore a handler where
+ old_xxx.sa_handler == SIG_IGN. That's what rl_maybe_restore_sighandler
+ does. Fewer system calls should reduce readline's per-line
+ overhead */
+ rl_maybe_restore_sighandler (SIGINT, &old_int);
+ rl_maybe_restore_sighandler (SIGTERM, &old_term);
+ rl_maybe_restore_sighandler (SIGHUP, &old_hup);
#if defined (SIGQUIT)
- rl_sigaction (SIGQUIT, &old_quit, &dummy);
+ rl_maybe_restore_sighandler (SIGQUIT, &old_quit);
#endif
#if defined (SIGALRM)
- rl_sigaction (SIGALRM, &old_alrm, &dummy);
+ rl_maybe_restore_sighandler (SIGALRM, &old_alrm);
#endif
#if defined (SIGTSTP)
- rl_sigaction (SIGTSTP, &old_tstp, &dummy);
+ rl_maybe_restore_sighandler (SIGTSTP, &old_tstp);
#endif /* SIGTSTP */
#if defined (SIGTTOU)
- rl_sigaction (SIGTTOU, &old_ttou, &dummy);
+ rl_maybe_restore_sighandler (SIGTTOU, &old_ttou);
#endif /* SIGTTOU */
#if defined (SIGTTIN)
- rl_sigaction (SIGTTIN, &old_ttin, &dummy);
+ rl_maybe_restore_sighandler (SIGTTIN, &old_ttin);
#endif /* SIGTTIN */
signals_set_flag = 0;
@@ -540,21 +596,6 @@ _rl_block_sigint ()
if (sigint_blocked)
return;
-#if defined (HAVE_POSIX_SIGNALS)
- sigemptyset (&sigint_set);
- sigemptyset (&sigint_oset);
- sigaddset (&sigint_set, SIGINT);
- sigprocmask (SIG_BLOCK, &sigint_set, &sigint_oset);
-#else /* !HAVE_POSIX_SIGNALS */
-# if defined (HAVE_BSD_SIGNALS)
- sigint_oldmask = sigblock (sigmask (SIGINT));
-# else /* !HAVE_BSD_SIGNALS */
-# if defined (HAVE_USG_SIGHOLD)
- sighold (SIGINT);
-# endif /* HAVE_USG_SIGHOLD */
-# endif /* !HAVE_BSD_SIGNALS */
-#endif /* !HAVE_POSIX_SIGNALS */
-
sigint_blocked = 1;
}
@@ -565,19 +606,8 @@ _rl_release_sigint ()
if (sigint_blocked == 0)
return;
-#if defined (HAVE_POSIX_SIGNALS)
- sigprocmask (SIG_SETMASK, &sigint_oset, (sigset_t *)NULL);
-#else
-# if defined (HAVE_BSD_SIGNALS)
- sigsetmask (sigint_oldmask);
-# else /* !HAVE_BSD_SIGNALS */
-# if defined (HAVE_USG_SIGHOLD)
- sigrelse (SIGINT);
-# endif /* HAVE_USG_SIGHOLD */
-# endif /* !HAVE_BSD_SIGNALS */
-#endif /* !HAVE_POSIX_SIGNALS */
-
sigint_blocked = 0;
+ RL_CHECK_SIGNALS ();
}
/* Cause SIGWINCH to not be delivered until the corresponding call to
@@ -588,6 +618,8 @@ _rl_block_sigwinch ()
if (sigwinch_blocked)
return;
+#if defined (SIGWINCH)
+
#if defined (HAVE_POSIX_SIGNALS)
sigemptyset (&sigwinch_set);
sigemptyset (&sigwinch_oset);
@@ -603,6 +635,8 @@ _rl_block_sigwinch ()
# endif /* !HAVE_BSD_SIGNALS */
#endif /* !HAVE_POSIX_SIGNALS */
+#endif /* SIGWINCH */
+
sigwinch_blocked = 1;
}
@@ -613,6 +647,8 @@ _rl_release_sigwinch ()
if (sigwinch_blocked == 0)
return;
+#if defined (SIGWINCH)
+
#if defined (HAVE_POSIX_SIGNALS)
sigprocmask (SIG_SETMASK, &sigwinch_oset, (sigset_t *)NULL);
#else
@@ -625,6 +661,8 @@ _rl_release_sigwinch ()
# endif /* !HAVE_BSD_SIGNALS */
#endif /* !HAVE_POSIX_SIGNALS */
+#endif /* SIGWINCH */
+
sigwinch_blocked = 0;
}
diff --git a/lib/readline/terminal.c b/lib/readline/terminal.c
index f8c2f6ed..1212ec46 100644
--- a/lib/readline/terminal.c
+++ b/lib/readline/terminal.c
@@ -55,6 +55,10 @@
# include <sys/ioctl.h>
#endif /* GWINSZ_IN_SYS_IOCTL && !TIOCGWINSZ */
+#ifdef __MSDOS__
+# include <pc.h>
+#endif
+
#include "rltty.h"
#include "tcap.h"
@@ -77,22 +81,25 @@ static void _win_get_screensize PARAMS((int *, int *));
static void _emx_get_screensize PARAMS((int *, int *));
#endif
-#define CUSTOM_REDISPLAY_FUNC() (rl_redisplay_function != rl_redisplay)
-#define CUSTOM_INPUT_FUNC() (rl_getc_function != rl_getc)
-
-/* If the calling application sets this to a non-zero value, readline will
- use the $LINES and $COLUMNS environment variables to set its idea of the
- window size before interrogating the kernel. */
+/* If the calling application sets this to a non-zero value, readline will
+ use the $LINES and $COLUMNS environment variables to set its idea of the
+ window size before interrogating the kernel. */
int rl_prefer_env_winsize = 0;
+/* If this is non-zero, readline will set LINES and COLUMNS in the
+ environment when it handles SIGWINCH. */
+int rl_change_environment = 1;
+
/* **************************************************************** */
/* */
/* Terminal and Termcap */
/* */
/* **************************************************************** */
+#ifndef __MSDOS__
static char *term_buffer = (char *)NULL;
static char *term_string_buffer = (char *)NULL;
+#endif
static int tcap_initialized;
@@ -264,7 +271,10 @@ _rl_get_screen_size (tty, ignore_env)
if (_rl_screenwidth <= 0)
_rl_screenwidth = wc;
-#if !defined (__DJGPP__)
+#if defined (__DJGPP__)
+ if (_rl_screenwidth <= 0)
+ _rl_screenwidth = ScreenCols ();
+#else
if (_rl_screenwidth <= 0 && term_string_buffer)
_rl_screenwidth = tgetnum ("co");
#endif
@@ -280,7 +290,10 @@ _rl_get_screen_size (tty, ignore_env)
if (_rl_screenheight <= 0)
_rl_screenheight = wr;
-#if !defined (__DJGPP__)
+#if defined (__DJGPP__)
+ if (_rl_screenheight <= 0)
+ _rl_screenheight = ScreenRows ();
+#else
if (_rl_screenheight <= 0 && term_string_buffer)
_rl_screenheight = tgetnum ("li");
#endif
@@ -296,7 +309,8 @@ _rl_get_screen_size (tty, ignore_env)
/* If we're being compiled as part of bash, set the environment
variables $LINES and $COLUMNS to new values. Otherwise, just
do a pair of putenv () or setenv () calls. */
- sh_set_lines_and_columns (_rl_screenheight, _rl_screenwidth);
+ if (rl_change_environment)
+ sh_set_lines_and_columns (_rl_screenheight, _rl_screenwidth);
if (_rl_term_autowrap == 0)
_rl_screenwidth--;
@@ -346,7 +360,13 @@ rl_reset_screen_size ()
{
_rl_get_screen_size (fileno (rl_instream), 0);
}
-
+
+void
+_rl_sigwinch_resize_terminal ()
+{
+ _rl_get_screen_size (fileno (rl_instream), 1);
+}
+
void
rl_resize_terminal ()
{
@@ -432,6 +452,23 @@ _rl_init_terminal_io (terminal_name)
if (term == 0)
term = "dumb";
+#ifdef __MSDOS__
+ _rl_term_im = _rl_term_ei = _rl_term_ic = _rl_term_IC = (char *)NULL;
+ _rl_term_up = _rl_term_dc = _rl_term_DC = _rl_visible_bell = (char *)NULL;
+ _rl_term_ku = _rl_term_kd = _rl_term_kl = _rl_term_kr = (char *)NULL;
+ _rl_term_mm = _rl_term_mo = (char *)NULL;
+ _rl_terminal_can_insert = term_has_meta = _rl_term_autowrap = 0;
+ _rl_term_cr = "\r";
+ _rl_term_clreol = _rl_term_clrpag = _rl_term_backspace = (char *)NULL;
+ _rl_term_goto = _rl_term_pc = _rl_term_ip = (char *)NULL;
+ _rl_term_ks = _rl_term_ke =_rl_term_vs = _rl_term_ve = (char *)NULL;
+ _rl_term_kh = _rl_term_kH = _rl_term_at7 = _rl_term_kI = (char *)NULL;
+#if defined(HACK_TERMCAP_MOTION)
+ _rl_term_forward_char = (char *)NULL;
+#endif
+
+ _rl_get_screen_size (tty, 0);
+#else /* !__MSDOS__ */
/* I've separated this out for later work on not calling tgetent at all
if the calling application has supplied a custom redisplay function,
(and possibly if the application has supplied a custom input function). */
@@ -531,6 +568,7 @@ _rl_init_terminal_io (terminal_name)
term_has_meta = tgetflag ("km") != 0;
if (term_has_meta == 0)
_rl_term_mm = _rl_term_mo = (char *)NULL;
+#endif /* !__MSDOS__ */
/* Attempt to find and bind the arrow keys. Do not override already
bound keys in an overzealous attempt, however. */
@@ -628,10 +666,12 @@ _rl_backspace (count)
{
register int i;
+#ifndef __MSDOS__
if (_rl_term_backspace)
for (i = 0; i < count; i++)
tputs (_rl_term_backspace, 1, _rl_output_character_function);
else
+#endif
for (i = 0; i < count; i++)
putc ('\b', _rl_out_stream);
return 0;
@@ -663,7 +703,11 @@ rl_ding ()
case VISIBLE_BELL:
if (_rl_visible_bell)
{
+#ifdef __DJGPP__
+ ScreenVisualBell ();
+#else
tputs (_rl_visible_bell, 1, _rl_output_character_function);
+#endif
break;
}
/* FALLTHROUGH */
@@ -683,12 +727,29 @@ rl_ding ()
/* */
/* **************************************************************** */
+static int enabled_meta = 0; /* flag indicating we enabled meta mode */
+
void
_rl_enable_meta_key ()
{
#if !defined (__DJGPP__)
if (term_has_meta && _rl_term_mm)
- tputs (_rl_term_mm, 1, _rl_output_character_function);
+ {
+ tputs (_rl_term_mm, 1, _rl_output_character_function);
+ enabled_meta = 1;
+ }
+#endif
+}
+
+void
+_rl_disable_meta_key ()
+{
+#if !defined (__DJGPP__)
+ if (term_has_meta && _rl_term_mo && enabled_meta)
+ {
+ tputs (_rl_term_mo, 1, _rl_output_character_function);
+ enabled_meta = 0;
+ }
#endif
}
@@ -718,6 +779,7 @@ void
_rl_set_cursor (im, force)
int im, force;
{
+#ifndef __MSDOS__
if (_rl_term_ve && _rl_term_vs)
{
if (force || im != rl_insert_mode)
@@ -728,4 +790,5 @@ _rl_set_cursor (im, force)
tputs (_rl_term_ve, 1, _rl_output_character_function);
}
}
+#endif
}
diff --git a/lib/readline/text.c b/lib/readline/text.c
index 536e31af..f29adf81 100644
--- a/lib/readline/text.c
+++ b/lib/readline/text.c
@@ -240,7 +240,7 @@ rl_replace_line (text, clear_undo)
this is the same as rl_end.
Any command that is called interactively receives two arguments.
- The first is a count: the numeric arg pased to this command.
+ The first is a count: the numeric arg passed to this command.
The second is the key which invoked this command.
*/
@@ -826,7 +826,7 @@ _rl_insert_char (count, c)
pending characters that are bound to rl_insert, and insert
them all. Don't do this if we're current reading input from
a macro. */
- if ((RL_ISSTATE (RL_STATE_MACROINPUT) == 0) && _rl_any_typein ())
+ if ((RL_ISSTATE (RL_STATE_MACROINPUT) == 0) && _rl_pushed_input_available ())
_rl_insert_typein (c);
else
{
@@ -908,6 +908,9 @@ _rl_insert_next (count)
if (c < 0)
return -1;
+ if (RL_ISSTATE (RL_STATE_MACRODEF))
+ _rl_add_macro_char (c);
+
#if defined (HANDLE_SIGNALS)
if (RL_ISSTATE (RL_STATE_CALLBACK) == 0)
_rl_restore_tty_signals ();
diff --git a/lib/readline/undo.c b/lib/readline/undo.c
index eb042b29..e9369b1a 100644
--- a/lib/readline/undo.c
+++ b/lib/readline/undo.c
@@ -1,7 +1,7 @@
/* readline.c -- a general facility for reading lines of input
with emacs style editing and completion. */
-/* Copyright (C) 1987-2009 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2012 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.
@@ -101,23 +101,33 @@ rl_add_undo (what, start, end, text)
rl_undo_list = temp;
}
-/* Free the existing undo list. */
+/* Free an UNDO_LIST */
void
-rl_free_undo_list ()
+_rl_free_undo_list (ul)
+ UNDO_LIST *ul;
{
- UNDO_LIST *release, *orig_list;
+ UNDO_LIST *release;
- orig_list = rl_undo_list;
- while (rl_undo_list)
+ while (ul)
{
- release = rl_undo_list;
- rl_undo_list = rl_undo_list->next;
+ release = ul;
+ ul = ul->next;
if (release->what == UNDO_DELETE)
xfree (release->text);
xfree (release);
}
+}
+
+/* Free the existing undo list. */
+void
+rl_free_undo_list ()
+{
+ UNDO_LIST *release, *orig_list;
+
+ orig_list = rl_undo_list;
+ _rl_free_undo_list (rl_undo_list);
rl_undo_list = (UNDO_LIST *)NULL;
replace_history_data (-1, (histdata_t *)orig_list, (histdata_t *)NULL);
}
@@ -168,6 +178,7 @@ rl_do_undo ()
{
UNDO_LIST *release;
int waiting_for_begin, start, end;
+ HIST_ENTRY *cur, *temp;
#define TRANS(i) ((i) == -1 ? rl_point : ((i) == -2 ? rl_end : (i)))
@@ -222,6 +233,18 @@ rl_do_undo ()
release = rl_undo_list;
rl_undo_list = rl_undo_list->next;
+
+ /* If we are editing a history entry, make sure the change is replicated
+ in the history entry's line */
+ cur = current_history ();
+ if (cur && cur->data && (UNDO_LIST *)cur->data == release)
+ {
+ temp = replace_history_entry (where_history (), rl_line_buffer, (histdata_t)rl_undo_list);
+ xfree (temp->line);
+ FREE (temp->timestamp);
+ xfree (temp);
+ }
+
replace_history_data (-1, (histdata_t *)release, (histdata_t *)rl_undo_list);
xfree (release);
diff --git a/lib/readline/util.c b/lib/readline/util.c
index 6c68ad8d..fa3a6671 100644
--- a/lib/readline/util.c
+++ b/lib/readline/util.c
@@ -1,6 +1,6 @@
/* util.c -- readline utility functions */
-/* Copyright (C) 1987-2010 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2012 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.
@@ -108,7 +108,11 @@ _rl_abort_internal ()
_rl_pop_executing_macro ();
rl_last_func = (rl_command_func_t *)NULL;
+#if defined (HAVE_POSIX_SIGSETJMP)
+ siglongjmp (_rl_top_level, 1);
+#else
longjmp (_rl_top_level, 1);
+#endif
return (0);
}
@@ -369,11 +373,13 @@ _rl_strpbrk (string1, string2)
doesn't matter (strncasecmp). */
int
_rl_strnicmp (string1, string2, count)
- char *string1, *string2;
+ const char *string1;
+ const char *string2;
int count;
{
- register char *s1, *s2;
- int d;
+ register const char *s1;
+ register const char *s2;
+ register int d;
if (count <= 0 || (string1 == string2))
return 0;
@@ -389,7 +395,7 @@ _rl_strnicmp (string1, string2, count)
break;
s2++;
}
- while (--count != 0)
+ while (--count != 0);
return (0);
}
@@ -397,10 +403,12 @@ _rl_strnicmp (string1, string2, count)
/* strcmp (), but caseless (strcasecmp). */
int
_rl_stricmp (string1, string2)
- char *string1, *string2;
+ const char *string1;
+ const char *string2;
{
- register char *s1, *s2;
- int d;
+ register const char *s1;
+ register const char *s2;
+ register int d;
s1 = string1;
s2 = string2;
@@ -507,7 +515,7 @@ _rl_tropen ()
if (_rl_tracefp)
fclose (_rl_tracefp);
- sprintf (fnbuf, "/var/tmp/rltrace.%ld", getpid());
+ sprintf (fnbuf, "/var/tmp/rltrace.%ld", (long)getpid());
unlink(fnbuf);
_rl_tracefp = fopen (fnbuf, "w+");
return _rl_tracefp != 0;
@@ -523,4 +531,61 @@ _rl_trclose ()
return r;
}
+void
+_rl_settracefp (fp)
+ FILE *fp;
+{
+ _rl_tracefp = fp;
+}
+#endif
+
+
+#if HAVE_DECL_AUDIT_USER_TTY && defined (ENABLE_TTY_AUDIT_SUPPORT)
+#include <sys/socket.h>
+#include <linux/audit.h>
+#include <linux/netlink.h>
+
+/* Report STRING to the audit system. */
+void
+_rl_audit_tty (string)
+ char *string;
+{
+ struct sockaddr_nl addr;
+ struct msghdr msg;
+ struct nlmsghdr nlm;
+ struct iovec iov[2];
+ size_t size;
+ int fd;
+
+ fd = socket (AF_NETLINK, SOCK_RAW, NETLINK_AUDIT);
+ if (fd < 0)
+ return;
+ size = strlen (string) + 1;
+
+ nlm.nlmsg_len = NLMSG_LENGTH (size);
+ nlm.nlmsg_type = AUDIT_USER_TTY;
+ nlm.nlmsg_flags = NLM_F_REQUEST;
+ nlm.nlmsg_seq = 0;
+ nlm.nlmsg_pid = 0;
+
+ iov[0].iov_base = &nlm;
+ iov[0].iov_len = sizeof (nlm);
+ iov[1].iov_base = string;
+ iov[1].iov_len = size;
+
+ addr.nl_family = AF_NETLINK;
+ addr.nl_pid = 0;
+ addr.nl_groups = 0;
+
+ msg.msg_name = &addr;
+ msg.msg_namelen = sizeof (addr);
+ msg.msg_iov = iov;
+ msg.msg_iovlen = 2;
+ msg.msg_control = NULL;
+ msg.msg_controllen = 0;
+ msg.msg_flags = 0;
+
+ (void)sendmsg (fd, &msg, 0);
+ close (fd);
+}
#endif
diff --git a/lib/readline/vi_keymap.c b/lib/readline/vi_keymap.c
index ba5a27ba..60c925d9 100644
--- a/lib/readline/vi_keymap.c
+++ b/lib/readline/vi_keymap.c
@@ -309,7 +309,6 @@ KEYMAP_ENTRY_ARRAY vi_movement_keymap = {
#endif /* KEYMAP_SIZE > 128 */
};
-
KEYMAP_ENTRY_ARRAY vi_insertion_keymap = {
/* The regular control keys come first. */
{ ISFUNC, (rl_command_func_t *)0x0 }, /* Control-@ */
diff --git a/lib/readline/vi_mode.c b/lib/readline/vi_mode.c
index 4408053f..0864192e 100644
--- a/lib/readline/vi_mode.c
+++ b/lib/readline/vi_mode.c
@@ -1,7 +1,7 @@
/* vi_mode.c -- A vi emulation mode for Bash.
Derived from code written by Jeff Sparkes (jsparkes@bnr.ca). */
-/* Copyright (C) 1987-2010 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2012 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.
@@ -108,9 +108,13 @@ static const char * const vi_textmod = "_*\\AaIiCcDdPpYyRrSsXx~";
/* Arrays for the saved marks. */
static int vi_mark_chars['z' - 'a' + 1];
+static void _rl_vi_replace_insert PARAMS((int));
+static void _rl_vi_save_replace PARAMS((void));
static void _rl_vi_stuff_insert PARAMS((int));
static void _rl_vi_save_insert PARAMS((UNDO_LIST *));
+static void vi_save_insert_buffer PARAMS ((int, int));
+
static void _rl_vi_backup PARAMS((void));
static int _rl_vi_arg_dispatch PARAMS((int));
@@ -189,6 +193,22 @@ _rl_vi_textmod_command (c)
}
static void
+_rl_vi_replace_insert (count)
+ int count;
+{
+ int nchars;
+
+ nchars = strlen (vi_insert_buffer);
+
+ rl_begin_undo_group ();
+ while (count--)
+ /* nchars-1 to compensate for _rl_replace_text using `end+1' in call
+ to rl_delete_text */
+ _rl_replace_text (vi_insert_buffer, rl_point, rl_point+nchars-1);
+ rl_end_undo_group ();
+}
+
+static void
_rl_vi_stuff_insert (count)
int count;
{
@@ -207,7 +227,7 @@ rl_vi_redo (count, c)
{
int r;
- if (!rl_explicit_arg)
+ if (rl_explicit_arg == 0)
{
rl_numeric_arg = _rl_vi_last_repeat;
rl_arg_sign = _rl_vi_last_arg_sign;
@@ -224,6 +244,13 @@ rl_vi_redo (count, c)
if (rl_point > 0)
_rl_vi_backup ();
}
+ else if (_rl_vi_last_command == 'R' && vi_insert_buffer && *vi_insert_buffer)
+ {
+ _rl_vi_replace_insert (count);
+ /* And back up point over the last character inserted. */
+ if (rl_point > 0)
+ _rl_vi_backup ();
+ }
/* Ditto for redoing an insert with `I', but move to the beginning of the
line like the `I' command does. */
else if (_rl_vi_last_command == 'I' && vi_insert_buffer && *vi_insert_buffer)
@@ -679,6 +706,8 @@ rl_vi_insertion_mode (count, key)
{
_rl_keymap = vi_insertion_keymap;
_rl_vi_last_key_before_insert = key;
+ if (_rl_show_mode_in_prompt)
+ _rl_reset_prompt ();
return (0);
}
@@ -691,6 +720,43 @@ rl_vi_insert_mode (count, key)
}
static void
+vi_save_insert_buffer (start, len)
+ int start, len;
+{
+ /* Same code as _rl_vi_save_insert below */
+ if (len >= vi_insert_buffer_size)
+ {
+ vi_insert_buffer_size += (len + 32) - (len % 32);
+ vi_insert_buffer = (char *)xrealloc (vi_insert_buffer, vi_insert_buffer_size);
+ }
+ strncpy (vi_insert_buffer, rl_line_buffer + start, len - 1);
+ vi_insert_buffer[len-1] = '\0';
+}
+
+static void
+_rl_vi_save_replace ()
+{
+ int len, start, end;
+ UNDO_LIST *up;
+
+ up = rl_undo_list;
+ if (up == 0 || up->what != UNDO_END || vi_replace_count <= 0)
+ {
+ if (vi_insert_buffer_size >= 1)
+ vi_insert_buffer[0] = '\0';
+ return;
+ }
+ /* Let's try it the quick and easy way for now. This should essentially
+ accommodate every UNDO_INSERT and save the inserted text to
+ vi_insert_buffer */
+ end = rl_point;
+ start = end - vi_replace_count + 1;
+ len = vi_replace_count + 1;
+
+ vi_save_insert_buffer (start, len);
+}
+
+static void
_rl_vi_save_insert (up)
UNDO_LIST *up;
{
@@ -706,13 +772,8 @@ _rl_vi_save_insert (up)
start = up->start;
end = up->end;
len = end - start + 1;
- if (len >= vi_insert_buffer_size)
- {
- vi_insert_buffer_size += (len + 32) - (len % 32);
- vi_insert_buffer = (char *)xrealloc (vi_insert_buffer, vi_insert_buffer_size);
- }
- strncpy (vi_insert_buffer, rl_line_buffer + start, len - 1);
- vi_insert_buffer[len-1] = '\0';
+
+ vi_save_insert_buffer (start, len);
}
void
@@ -728,7 +789,10 @@ _rl_vi_done_inserting ()
on absolute indices into the line which may change (though they
probably will not). */
_rl_vi_doing_insert = 0;
- _rl_vi_save_insert (rl_undo_list->next);
+ if (_rl_vi_last_key_before_insert == 'R')
+ _rl_vi_save_replace (); /* Half the battle */
+ else
+ _rl_vi_save_insert (rl_undo_list->next);
vi_continued_command = 1;
}
else
@@ -762,6 +826,9 @@ rl_vi_movement_mode (count, key)
if (RL_ISSTATE (RL_STATE_VICMDONCE) == 0)
rl_free_undo_list ();
+ if (_rl_show_mode_in_prompt)
+ _rl_reset_prompt ();
+
RL_SETSTATE (RL_STATE_VICMDONCE);
return (0);
}
@@ -1940,14 +2007,20 @@ rl_vi_replace (count, key)
vi_replace_count = 0;
- if (!vi_replace_map)
+ if (vi_replace_map == 0)
{
vi_replace_map = rl_make_bare_keymap ();
+ for (i = 0; i < ' '; i++)
+ if (vi_insertion_keymap[i].type == ISFUNC)
+ vi_replace_map[i].function = vi_insertion_keymap[i].function;
+
for (i = ' '; i < KEYMAP_SIZE; i++)
vi_replace_map[i].function = rl_vi_overstrike;
vi_replace_map[RUBOUT].function = rl_vi_overstrike_delete;
+
+ /* Make sure these are what we want. */
vi_replace_map[ESC].function = rl_vi_movement_mode;
vi_replace_map[RETURN].function = rl_newline;
vi_replace_map[NEWLINE].function = rl_newline;
@@ -1960,7 +2033,12 @@ rl_vi_replace (count, key)
vi_replace_map[CTRL ('H')].function = rl_vi_overstrike_delete;
}
+
+ rl_vi_start_inserting (key, 1, rl_arg_sign);
+
+ _rl_vi_last_key_before_insert = key;
_rl_keymap = vi_replace_map;
+
return (0);
}
diff --git a/lib/sh/Makefile.in b/lib/sh/Makefile.in
index d97cd99b..36a83052 100644
--- a/lib/sh/Makefile.in
+++ b/lib/sh/Makefile.in
@@ -92,7 +92,7 @@ CSOURCES = clktck.c clock.c getcwd.c getenv.c oslib.c setlinebuf.c \
mktime.c strftime.c mbschr.c zcatfd.c zmapfd.c winsize.c eaccess.c \
wcsdup.c fpurge.c zgetline.c mbscmp.c uconvert.c ufuncs.c \
casemod.c dprintf.c input_avail.c mbscasecmp.c fnxform.c \
- strchrnul.c unicode.c wcswidth.c shmbchar.c
+ strchrnul.c unicode.c wcswidth.c wcsnwidth.c shmbchar.c strdup.c
# The header files for this library.
HSOURCES =
@@ -106,7 +106,8 @@ OBJECTS = clktck.o clock.o getenv.o oslib.o setlinebuf.o strnlen.o \
strtrans.o snprintf.o mailstat.o fmtulong.o \
fmtullong.o fmtumax.o zcatfd.o zmapfd.o winsize.o wcsdup.o \
fpurge.o zgetline.o mbscmp.o uconvert.o ufuncs.o casemod.o \
- input_avail.o mbscasecmp.o fnxform.o unicode.o shmbchar.o ${LIBOBJS}
+ input_avail.o mbscasecmp.o fnxform.o unicode.o shmbchar.o \
+ wcsnwidth.o ${LIBOBJS}
SUPPORT = Makefile
@@ -197,6 +198,7 @@ uconvert.o: uconvert.c
ufuncs.o: ufuncs.c
vprint.o: vprint.c
wcsdup.o: wcsdup.c
+wcsnwidth.o: wcsnwidth.c
wcswidth.o: wcswidth.c
mbschr.o: mbschr.c
zcatfd.o: zcatfd.c
@@ -269,6 +271,7 @@ uconvert.o: ${BUILD_DIR}/config.h
ufuncs.o: ${BUILD_DIR}/config.h
vprint.o: ${BUILD_DIR}/config.h
wcsdup.o: ${BUILD_DIR}/config.h
+wcsnwidth.o: ${BUILD_DIR}/config.h
wcswidth.o: ${BUILD_DIR}/config.h
mbschr.o: ${BUILD_DIR}/config.h
zcatfd.o: ${BUILD_DIR}/config.h
@@ -291,7 +294,7 @@ 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: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
-getenv.o: ${BUILD_DIR}/version.h
+#getenv.o: ${BUILD_DIR}/version.h
inet_aton.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
inet_aton.o: ${BASHINCDIR}/stdc.h
@@ -303,7 +306,8 @@ 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: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
+itos.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
+#itos.o: ${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
@@ -312,7 +316,8 @@ 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: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
+makepath.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
+#makepath.o: ${BUILD_DIR}/version.h
netconn.o: ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/filecntl.h
netconn.o: ${topdir}/bashtypes.h
@@ -324,8 +329,9 @@ 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: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
+netopen.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
netopen.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+#netopen.o: ${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
@@ -334,9 +340,10 @@ 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: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
+oslib.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
oslib.o: ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/filecntl.h
oslib.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
+#oslib.o: ${BUILD_DIR}/version.h
pathcanon.o: ${topdir}/bashtypes.h ${topdir}/bashansi.h ${BASHINCDIR}/maxpath.h
pathcanon.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
@@ -345,9 +352,10 @@ 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: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
+pathcanon.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
pathcanon.o: ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/filecntl.h
pathcanon.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
+#pathcanon.o: ${BUILD_DIR}/version.h
pathphys.o: ${topdir}/bashtypes.h ${topdir}/bashansi.h ${BASHINCDIR}/maxpath.h
pathphys.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
@@ -356,9 +364,10 @@ 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: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
+pathphys.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
pathphys.o: ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/filecntl.h
pathphys.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
+#pathphys.o: ${BUILD_DIR}/version.h
rename.o: ${topdir}/bashtypes.h ${BASHINCDIR}/stdc.h
rename.o: ${BASHINCDIR}/posixstat.h
@@ -377,7 +386,8 @@ eaccess.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${top
eaccess.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
eaccess.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
eaccess.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
-eaccess.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
+eaccess.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
+#eaccess.o: ${BUILD_DIR}/version.h
shquote.o: ${BASHINCDIR}/stdc.h ${topdir}/bashansi.h
shquote.o: ${BASHINCDIR}/ansi_stdlib.h ${topdir}/xmalloc.h
@@ -403,7 +413,8 @@ 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: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
+strerror.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
+#strerror.o: ${BUILD_DIR}/version.h
strcasestr.o: ${BASHINCDIR}/stdc.h ${topdir}/bashansi.h
strcasestr.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
@@ -415,7 +426,8 @@ 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: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
+stringlist.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
+#stringlist.o: ${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
@@ -424,7 +436,8 @@ 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: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
+stringvec.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
+#stringvec.o: ${BUILD_DIR}/version.h
strnlen.o: ${BASHINCDIR}/stdc.h
@@ -461,7 +474,8 @@ 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: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
+strtrans.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
+#strtrans.o: ${BUILD_DIR}/version.h
times.o: ${BASHINCDIR}/systimes.h
times.o: ${BASHINCDIR}/posixtime.h
@@ -510,6 +524,9 @@ wcsdup.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
wcsdup.o: ${BASHINCDIR}/stdc.h
wcsdup.o: ${topdir}/xmalloc.h
+wcsnwidth.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+wcsnwidth.o: ${BASHINCDIR}/stdc.h
+
wcswidth.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
wcswidth.o: ${BASHINCDIR}/stdc.h
diff --git a/lib/sh/casemod.c b/lib/sh/casemod.c
index 3127d8c4..bbcffa6f 100644
--- a/lib/sh/casemod.c
+++ b/lib/sh/casemod.c
@@ -36,8 +36,10 @@
#include <ctype.h>
#include <xmalloc.h>
+#include <shmbchar.h>
#include <shmbutil.h>
#include <chartypes.h>
+#include <typemax.h>
#include <glob/strmatch.h>
@@ -67,6 +69,10 @@
extern char *substring __P((char *, int, int));
+#ifndef UCHAR_MAX
+# define UCHAR_MAX TYPE_MAXIMUM(unsigned char)
+#endif
+
#if defined (HANDLE_MULTIBYTE)
static wchar_t
cval (s, i)
@@ -78,7 +84,7 @@ cval (s, i)
int l;
mbstate_t mps;
- if (MB_CUR_MAX == 1)
+ if (MB_CUR_MAX == 1 || is_basic (s[i]))
return ((wchar_t)s[i]);
l = strlen (s);
if (i >= (l - 1))
@@ -140,8 +146,10 @@ sh_modcase (string, pat, flags)
if (iswalnum (wc) == 0)
{
inword = 0;
+#if 0
ADVANCE_CHAR (ret, end, start);
continue;
+#endif
}
if (pat)
@@ -202,8 +210,11 @@ sh_modcase (string, pat, flags)
else
nop = flags;
- if (MB_CUR_MAX == 1 || isascii (wc))
+ /* Need to check UCHAR_MAX since wc may have already been converted to a
+ wide character by cval() */
+ if (MB_CUR_MAX == 1 || (wc <= UCHAR_MAX && is_basic ((int)wc)))
{
+singlebyte:
switch (nop)
{
default:
@@ -220,15 +231,18 @@ sh_modcase (string, pat, flags)
{
m = mbrtowc (&wc, string + start, end - start, &state);
if (MB_INVALIDCH (m))
- wc = (wchar_t)string[start];
+ {
+ wc = (unsigned char)string[start];
+ goto singlebyte;
+ }
else if (MB_NULLWCH (m))
wc = L'\0';
switch (nop)
{
default:
case CASE_NOOP: nwc = wc; break;
- case CASE_UPPER: nwc = TOUPPER (wc); break;
- case CASE_LOWER: nwc = TOLOWER (wc); break;
+ case CASE_UPPER: nwc = _to_wupper (wc); break;
+ case CASE_LOWER: nwc = _to_wlower (wc); break;
case CASE_TOGGLEALL:
case CASE_TOGGLE: nwc = TOGGLE (wc); break;
}
diff --git a/lib/sh/clktck.c b/lib/sh/clktck.c
index 096ce06e..8b9b5b32 100644
--- a/lib/sh/clktck.c
+++ b/lib/sh/clktck.c
@@ -21,7 +21,9 @@
#include <config.h>
#include <bashtypes.h>
-#include <sys/param.h>
+#if defined (HAVE_SYS_PARAM_H)
+# include <sys/param.h>
+#endif
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
diff --git a/lib/sh/eaccess.c b/lib/sh/eaccess.c
index 534c526b..8132a9ab 100644
--- a/lib/sh/eaccess.c
+++ b/lib/sh/eaccess.c
@@ -205,14 +205,16 @@ sh_eaccess (path, mode)
if (path_is_devfd (path))
return (sh_stataccess (path, mode));
-#if defined (HAVE_FACCESSAT) && defined (AT_EACCESS)
- return (faccessat (AT_FDCWD, path, mode, AT_EACCESS));
-#elif defined (HAVE_EACCESS) /* FreeBSD */
+#if (defined (HAVE_FACCESSAT) && defined (AT_EACCESS)) || defined (HAVE_EACCESS)
+# if defined (HAVE_FACCESSAT) && defined (AT_EACCESS)
+ ret = faccessat (AT_FDCWD, path, mode, AT_EACCESS);
+# else /* HAVE_EACCESS */ /* FreeBSD */
ret = eaccess (path, mode); /* XXX -- not always correct for X_OK */
-# if defined (__FreeBSD__)
+# endif /* HAVE_EACCESS */
+# if defined (__FreeBSD__) || defined (SOLARIS)
if (ret == 0 && current_user.euid == 0 && mode == X_OK)
return (sh_stataccess (path, mode));
-# endif
+# endif /* __FreeBSD__ || SOLARIS */
return ret;
#elif defined (EFF_ONLY_OK) /* SVR4(?), SVR4.2 */
return access (path, mode|EFF_ONLY_OK);
@@ -233,7 +235,6 @@ sh_eaccess (path, mode)
return (sh_stataccess (path, mode));
#endif
return ret;
-
}
return (sh_stataccess (path, mode));
diff --git a/lib/sh/fmtulong.c b/lib/sh/fmtulong.c
index 214b1466..0ccc22b4 100644
--- a/lib/sh/fmtulong.c
+++ b/lib/sh/fmtulong.c
@@ -1,6 +1,6 @@
/* fmtulong.c -- Convert unsigned long int to string. */
-/* Copyright (C) 1998-2002 Free Software Foundation, Inc.
+/* Copyright (C) 1998-2011 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -98,8 +98,9 @@ fmtulong (ui, base, buf, len, flags)
if (base < 2 || base > 64)
{
#if 1
+ /* XXX - truncation possible with long translation */
strncpy (buf, _("invalid base"), len - 1);
- buf[len] = '\0';
+ buf[len-1] = '\0';
errno = EINVAL;
return (p = buf);
#else
diff --git a/lib/sh/getcwd.c b/lib/sh/getcwd.c
index 07eb8171..d7bd241b 100644
--- a/lib/sh/getcwd.c
+++ b/lib/sh/getcwd.c
@@ -48,7 +48,7 @@
#include <bashansi.h>
-#if defined (BROKEN_DIRENT_D_INO)
+#if !defined (D_FILENO_AVAILABLE)
# include "command.h"
# include "general.h"
# include "externs.h"
@@ -71,7 +71,7 @@ extern int errno;
/* If the d_fileno member of a struct dirent doesn't return anything useful,
we need to check inode number equivalence the hard way. Return 1 if
the inode corresponding to PATH/DIR is identical to THISINO. */
-#if defined (BROKEN_DIRENT_D_INO)
+#if !defined (D_FILENO_AVAILABLE)
static int
_path_checkino (dotp, name, thisino)
char *dotp;
@@ -206,7 +206,7 @@ getcwd (buf, size)
(d->d_name[1] == '\0' ||
(d->d_name[1] == '.' && d->d_name[2] == '\0')))
continue;
-#if !defined (BROKEN_DIRENT_D_INO)
+#if defined (D_FILENO_AVAILABLE)
if (mount_point || d->d_fileno == thisino)
#else
if (mount_point || _path_checkino (dotp, d->d_name, thisino))
diff --git a/lib/sh/inet_aton.c b/lib/sh/inet_aton.c
index 4b48456f..e377178e 100644
--- a/lib/sh/inet_aton.c
+++ b/lib/sh/inet_aton.c
@@ -67,7 +67,9 @@ static char rcsid[] = "$Id: inet_addr.c,v 1.5 1996/08/14 03:48:37 drepper Exp $"
#if !defined (HAVE_INET_ATON) && defined (HAVE_NETWORK) && defined (HAVE_NETINET_IN_H) && defined (HAVE_ARPA_INET_H)
#include <sys/types.h>
+#if defined (HAVE_SYS_PARAM_H)
#include <sys/param.h>
+#endif
#include <netinet/in.h>
#include <arpa/inet.h>
diff --git a/lib/sh/itos.c b/lib/sh/itos.c
index 12e9398d..cd36ef33 100644
--- a/lib/sh/itos.c
+++ b/lib/sh/itos.c
@@ -50,6 +50,18 @@ itos (i)
return (savestring (p));
}
+/* Integer to string conversion. This conses the string using strdup;
+ caller should free it and be prepared to deal with NULL return. */
+char *
+mitos (i)
+ intmax_t i;
+{
+ char *p, lbuf[INT_STRLEN_BOUND(intmax_t) + 1];
+
+ p = fmtumax (i, 10, lbuf, sizeof(lbuf), 0);
+ return (strdup (p));
+}
+
char *
uinttostr (i, buf, len)
uintmax_t i;
diff --git a/lib/sh/mailstat.c b/lib/sh/mailstat.c
index 2b2ac0ea..79b431ae 100644
--- a/lib/sh/mailstat.c
+++ b/lib/sh/mailstat.c
@@ -28,7 +28,7 @@
#include <posixdir.h>
#include <bashansi.h>
-#ifndef _MINIX
+#if defined (HAVE_SYS_PARAM_H)
# include <sys/param.h>
#endif
diff --git a/lib/sh/makepath.c b/lib/sh/makepath.c
index 43dbab20..ef01718b 100644
--- a/lib/sh/makepath.c
+++ b/lib/sh/makepath.c
@@ -94,7 +94,7 @@ sh_makepath (path, dir, flags)
MAKEDOT();
}
else if ((flags & MP_IGNDOT) && path[0] == '.' && (path[1] == '\0' ||
- path[1] == '/' && path[2] == '\0'))
+ (path[1] == '/' && path[2] == '\0')))
{
xpath = nullpath;
pathlen = 0;
diff --git a/lib/sh/mbschr.c b/lib/sh/mbschr.c
index 5143d64e..7730e46e 100644
--- a/lib/sh/mbschr.c
+++ b/lib/sh/mbschr.c
@@ -27,6 +27,8 @@
#include "bashansi.h"
#include "shmbutil.h"
+extern int locale_mb_cur_max;
+
#undef mbschr
/* In some locales, the non-first byte of some multibyte characters have
@@ -51,7 +53,7 @@ mbschr (s, c)
GBK, GB18030, SHIFT_JIS, and JOHAB. They exhibit the problem only
when c >= 0x30. We can therefore use the faster bytewise search if
c <= 0x30. */
- if ((unsigned char)c >= '0' && MB_CUR_MAX > 1)
+ if ((unsigned char)c >= '0' && locale_mb_cur_max > 1)
{
pos = (char *)s;
memset (&state, '\0', sizeof(mbstate_t));
@@ -59,9 +61,14 @@ mbschr (s, c)
while (strlength > 0)
{
- mblength = mbrlen (pos, strlength, &state);
- if (mblength == (size_t)-2 || mblength == (size_t)-1 || mblength == (size_t)0)
+ if (is_basic (*pos))
mblength = 1;
+ else
+ {
+ mblength = mbrlen (pos, strlength, &state);
+ if (mblength == (size_t)-2 || mblength == (size_t)-1 || mblength == (size_t)0)
+ mblength = 1;
+ }
if (mblength == 1 && c == (unsigned char)*pos)
return pos;
diff --git a/lib/sh/mktime.c b/lib/sh/mktime.c
index 72574008..7888ee15 100644
--- a/lib/sh/mktime.c
+++ b/lib/sh/mktime.c
@@ -41,8 +41,6 @@
#ifndef VMS
#include <sys/types.h> /* Some systems define `time_t' here. */
-#else
-#include <stddef.h>
#endif
#include <time.h>
diff --git a/lib/sh/oslib.c b/lib/sh/oslib.c
index b3470d16..65eb99d9 100644
--- a/lib/sh/oslib.c
+++ b/lib/sh/oslib.c
@@ -21,7 +21,7 @@
#include <config.h>
#include <bashtypes.h>
-#ifndef _MINIX
+#if defined (HAVE_SYS_PARAM_H)
# include <sys/param.h>
#endif
@@ -124,7 +124,7 @@ dup2 (fd1, fd2)
/*
* Return the total number of available file descriptors.
*
- * On some systems, like 4.2BSD and its descendents, there is a system call
+ * On some systems, like 4.2BSD and its descendants, there is a system call
* that returns the size of the descriptor table: getdtablesize(). There are
* lots of ways to emulate this on non-BSD systems.
*
diff --git a/lib/sh/pathcanon.c b/lib/sh/pathcanon.c
index 98e41ced..f19bd55f 100644
--- a/lib/sh/pathcanon.c
+++ b/lib/sh/pathcanon.c
@@ -21,7 +21,7 @@
#include <config.h>
#include <bashtypes.h>
-#ifndef _MINIX
+#if defined (HAVE_SYS_PARAM_H)
# include <sys/param.h>
#endif
#include <posixstat.h>
diff --git a/lib/sh/pathphys.c b/lib/sh/pathphys.c
index 15fcd250..26016b76 100644
--- a/lib/sh/pathphys.c
+++ b/lib/sh/pathphys.c
@@ -21,7 +21,7 @@
#include <config.h>
#include <bashtypes.h>
-#ifndef _MINIX
+#if defined (HAVE_SYS_PARAM_H)
# include <sys/param.h>
#endif
#include <posixstat.h>
@@ -269,7 +269,7 @@ sh_realpath (pathname, resolved)
wd = get_working_directory ("sh_realpath");
if (wd == 0)
return ((char *)NULL);
- tdir = sh_makepath ((char *)pathname, wd, 0);
+ tdir = sh_makepath (wd, (char *)pathname, 0);
free (wd);
}
else
diff --git a/lib/sh/shmbchar.c b/lib/sh/shmbchar.c
index c5badc14..042c9f14 100644
--- a/lib/sh/shmbchar.c
+++ b/lib/sh/shmbchar.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001, 2006, 2009, 2010 Free Software Foundation, Inc.
+/* Copyright (C) 2001, 2006, 2009, 2010, 2012 Free Software Foundation, Inc.
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
@@ -89,4 +89,25 @@ mbsmbchar (s)
}
return 0;
}
+
+int
+sh_mbsnlen(src, srclen, maxlen)
+ const char *src;
+ size_t srclen;
+ int maxlen;
+{
+ int count;
+ int sind;
+ DECLARE_MBSTATE;
+
+ for (sind = count = 0; src[sind]; )
+ {
+ count++; /* number of multibyte characters */
+ ADVANCE_CHAR (src, srclen, sind);
+ if (sind > maxlen)
+ break;
+ }
+
+ return count;
+}
#endif
diff --git a/lib/sh/shquote.c b/lib/sh/shquote.c
index a1e9146b..31cce1c1 100644
--- a/lib/sh/shquote.c
+++ b/lib/sh/shquote.c
@@ -32,6 +32,50 @@
#include "syntax.h"
#include <xmalloc.h>
+/* Default set of characters that should be backslash-quoted in strings */
+static const char bstab[256] =
+ {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 0, 0, 0, 0, 0, /* TAB, NL */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ 1, 1, 1, 0, 1, 0, 1, 1, /* SPACE, !, DQUOTE, DOL, AMP, SQUOTE */
+ 1, 1, 1, 0, 1, 0, 0, 0, /* LPAR, RPAR, STAR, COMMA */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 1, 0, 1, 1, /* SEMI, LESSTHAN, GREATERTHAN, QUEST */
+
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 1, 1, 1, 0, /* LBRACK, BS, RBRACK, CARAT */
+
+ 1, 0, 0, 0, 0, 0, 0, 0, /* BACKQ */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 1, 1, 0, 0, /* LBRACE, BAR, RBRACE */
+
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ };
+
/* **************************************************************** */
/* */
/* Functions for quoting strings to be re-read as input */
@@ -50,6 +94,15 @@ sh_single_quote (string)
result = (char *)xmalloc (3 + (4 * strlen (string)));
r = result;
+
+ if (string[0] == '\'' && string[1] == 0)
+ {
+ *r++ = '\\';
+ *r++ = '\'';
+ *r++ = 0;
+ return result;
+ }
+
*r++ = '\'';
for (s = string; s && (c = *s); s++)
@@ -163,53 +216,33 @@ sh_un_double_quote (string)
way to protect the CTLESC and CTLNUL characters. As I write this,
the current callers will never cause the string to be expanded without
going through the shell parser, which will protect the internal
- quoting characters. */
+ quoting characters. TABLE, if set, points to a map of the ascii code
+ set with char needing to be backslash-quoted if table[char]==1. FLAGS,
+ if 1, causes tildes to be quoted as well. */
+
char *
-sh_backslash_quote (string)
+sh_backslash_quote (string, table, flags)
char *string;
+ char *table;
+ int flags;
{
int c;
- char *result, *r, *s;
+ char *result, *r, *s, *backslash_table;
result = (char *)xmalloc (2 * strlen (string) + 1);
+ backslash_table = table ? table : (char *)bstab;
for (r = result, s = string; s && (c = *s); s++)
{
- switch (c)
- {
- case ' ': case '\t': case '\n': /* IFS white space */
- case '\'': case '"': case '\\': /* quoting chars */
- case '|': case '&': case ';': /* shell metacharacters */
- case '(': case ')': case '<': case '>':
- case '!': case '{': case '}': /* reserved words */
- case '*': case '[': case '?': case ']': /* globbing chars */
- case '^':
- case '$': case '`': /* expansion chars */
- case ',': /* brace expansion */
- *r++ = '\\';
- *r++ = c;
- break;
-#if 0
- case '~': /* tilde expansion */
- if (s == string || s[-1] == '=' || s[-1] == ':')
- *r++ = '\\';
- *r++ = c;
- break;
-
- case CTLESC: case CTLNUL: /* internal quoting characters */
- *r++ = CTLESC; /* could be '\\'? */
- *r++ = c;
- break;
-#endif
-
- case '#': /* comment char */
- if (s == string)
- *r++ = '\\';
- /* FALLTHROUGH */
- default:
- *r++ = c;
- break;
- }
+ if (backslash_table[c] == 1)
+ *r++ = '\\';
+ else if (c == '#' && s == string) /* comment char */
+ *r++ = '\\';
+ else if ((flags&1) && c == '~' && (s == string || s[-1] == ':' || s[-1] == '='))
+ /* Tildes are special at the start of a word or after a `:' or `='
+ (technically unquoted, but it doesn't make a difference in practice) */
+ *r++ = '\\';
+ *r++ = c;
}
*r = '\0';
diff --git a/lib/sh/snprintf.c b/lib/sh/snprintf.c
index d46b2d9c..87ca2173 100644
--- a/lib/sh/snprintf.c
+++ b/lib/sh/snprintf.c
@@ -9,7 +9,7 @@
Unix snprintf implementation.
derived from inetutils/libinetutils/snprintf.c Version 1.1
- Copyright (C) 2001,2006,2010 Free Software Foundation, Inc.
+ Copyright (C) 2001,2006,2010,2012 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -26,7 +26,7 @@
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
- Revision History:
+ Original (pre-bash) Revision History:
1.1:
* added changes from Miles Bader
@@ -50,7 +50,6 @@
* 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 with ldfallback(), since underlying
* printf may not handle it -- should ideally have another autoconf test
*/
@@ -303,11 +302,30 @@ static void dfallback __P((struct DATA *, const char *, const char *, double));
static char *groupnum __P((char *));
-#ifndef HAVE_ISINF_IN_LIBC
-static int isinf __P((double));
+#if defined (HAVE_LONG_DOUBLE)
+# define LONGDOUBLE long double
+#else
+# define LONGDOUBLE double
+#endif
+
+#ifndef isnan
+ static inline int isnan_f (float x) { return x != x; }
+ static inline int isnan_d (double x) { return x != x; }
+ static inline int isnan_ld (LONGDOUBLE x) { return x != x; }
+ # define isnan(x) \
+ (sizeof (x) == sizeof (LONGDOUBLE) ? isnan_ld (x) \
+ : sizeof (x) == sizeof (double) ? isnan_d (x) \
+ : isnan_f (x))
#endif
-#ifndef HAVE_ISNAN_IN_LIBC
-static int isnan __P((double));
+
+#ifndef isinf
+ static inline int isinf_f (float x) { return !isnan (x) && isnan (x - x); }
+ static inline int isinf_d (double x) { return !isnan (x) && isnan (x - x); }
+ static inline int isinf_ld (LONGDOUBLE x) { return !isnan (x) && isnan (x - x); }
+ # define isinf(x) \
+ (sizeof (x) == sizeof (LONGDOUBLE) ? isinf_ld (x) \
+ : sizeof (x) == sizeof (double) ? isinf_d (x) \
+ : isinf_f (x))
#endif
#ifdef DRIVER
@@ -371,7 +389,7 @@ static void xfree __P((void *));
while (0)
#define PUT_PLUS(d, p, zero) \
- if ((d) > zero && (p)->justify == RIGHT) \
+ if (((p)->flags & PF_PLUS) && (d) > zero) \
PUT_CHAR('+', p)
#define PUT_SPACE(d, p, zero) \
@@ -431,9 +449,9 @@ static void xfree __P((void *));
if (lv) \
{ \
if (lv->decimal_point && lv->decimal_point[0]) \
- (d) = lv->decimal_point[0]; \
+ (d) = lv->decimal_point[0]; \
if (lv->thousands_sep && lv->thousands_sep[0]) \
- (t) = lv->thousands_sep[0]; \
+ (t) = lv->thousands_sep[0]; \
(g) = lv->grouping ? lv->grouping : ""; \
if (*(g) == '\0' || *(g) == CHAR_MAX || (t) == -1) (g) = 0; \
} \
@@ -574,7 +592,7 @@ integral(real, ip)
/*
* return an ascii representation of the integral part of the number
* and set fract to be an ascii representation of the fraction part
- * the container for the fraction and the integral part or staticly
+ * the container for the fraction and the integral part or statically
* declare with fix size
*/
static char *
@@ -586,10 +604,9 @@ numtoa(number, base, precision, fract)
register int i, j;
double ip, fp; /* integer and fraction part */
double fraction;
- int digits = MAX_INT - 1;
+ int digits, sign;
static char integral_part[MAX_INT];
static char fraction_part[MAX_FRACT];
- double sign;
int ch;
/* taking care of the obvious case: 0.0 */
@@ -607,8 +624,12 @@ numtoa(number, base, precision, fract)
return integral_part;
}
+ /* -0 is tricky */
+ sign = (number == -0.) ? '-' : ((number < 0.) ? '-' : '+');
+ digits = MAX_INT - 1;
+
/* for negative numbers */
- if ((sign = number) < 0.)
+ if (sign == '-')
{
number = -number;
digits--; /* sign consume one digit */
@@ -643,7 +664,7 @@ numtoa(number, base, precision, fract)
integral_part[i] = '9';
/* put the sign ? */
- if (sign < 0.)
+ if (sign == '-')
integral_part[i++] = '-';
integral_part[i] = '\0';
@@ -682,9 +703,13 @@ number(p, d, base)
long sd;
int flags;
- /* An explicit precision turns off the zero-padding flag. */
+ /* An explicit precision turns off the zero-padding flag and sets the
+ pad character back to space. */
if ((p->flags & PF_ZEROPAD) && p->precision >= 0 && (p->flags & PF_DOT))
- p->flags &= ~PF_ZEROPAD;
+ {
+ p->flags &= ~PF_ZEROPAD;
+ p->pad = ' ';
+ }
sd = d; /* signed for ' ' padding in base 10 */
flags = 0;
@@ -698,10 +723,11 @@ number(p, d, base)
{
GETLOCALEDATA(decpoint, thoussep, grouping);
if (grouping && (t = groupnum (tmp)))
- tmp = t;
+ tmp = t;
}
- p->width -= strlen(tmp);
+ /* need to add one for any `+', but we only add one in base 10 */
+ p->width -= strlen(tmp) + (base == 10 && d > 0 && (p->flags & PF_PLUS));
PAD_RIGHT(p);
if ((p->flags & PF_DOT) && p->precision > 0)
@@ -753,9 +779,13 @@ lnumber(p, d, base)
long long sd;
int flags;
- /* An explicit precision turns off the zero-padding flag. */
+ /* An explicit precision turns off the zero-padding flag and sets the
+ pad character back to space. */
if ((p->flags & PF_ZEROPAD) && p->precision >= 0 && (p->flags & PF_DOT))
- p->flags &= ~PF_ZEROPAD;
+ {
+ p->flags &= ~PF_ZEROPAD;
+ p->pad = ' ';
+ }
sd = d; /* signed for ' ' padding in base 10 */
flags = (*p->pf == 'x' || *p->pf == 'X' || *p->pf == 'o' || *p->pf == 'u' || *p->pf == 'U') ? FL_UNSIGNED : 0;
@@ -768,10 +798,11 @@ lnumber(p, d, base)
{
GETLOCALEDATA(decpoint, thoussep, grouping);
if (grouping && (t = groupnum (tmp)))
- tmp = t;
+ tmp = t;
}
- p->width -= strlen(tmp);
+ /* need to add one for any `+', but we only add one in base 10 */
+ p->width -= strlen(tmp) + (base == 10 && d > 0 && (p->flags & PF_PLUS));
PAD_RIGHT(p);
if ((p->flags & PF_DOT) && p->precision > 0)
@@ -875,11 +906,11 @@ wstrings(p, tmp)
{
len = wcsrtombs (NULL, &ws, 0, &mbs);
if (len != (size_t)-1)
- {
+ {
memset (&mbs, '\0', sizeof (mbstate_t));
os = (char *)xmalloc (len + 1);
(void)wcsrtombs (os, &ws, len + 1, &mbs);
- }
+ }
}
if (len == (size_t)-1)
{
@@ -919,32 +950,6 @@ wchars (p, wc)
#ifdef FLOATING_POINT
-#ifndef HAVE_ISINF_IN_LIBC
-/* Half-assed versions, since we don't want to link with libm. */
-static int
-isinf(d)
- double d;
-{
-#ifdef DBL_MAX
- if (d < DBL_MIN)
- return -1;
- else if (d > DBL_MAX)
- return 1;
- else
-#endif
- return 0;
-}
-#endif
-
-#ifndef HAVE_ISNAN_IN_LIBC
-static int
-isnan(d)
- double d;
-{
- return 0;
-}
-#endif
-
/* Check for [+-]infinity and NaN. If MODE == 1, we check for Infinity, else
(mode == 2) we check for NaN. This does the necessary printing. Returns
1 if Inf or Nan, 0 if not. */
@@ -1002,19 +1007,35 @@ floating(p, d)
{
/* smash the trailing zeros unless altform */
for (i = strlen(tmp2) - 1; i >= 0 && tmp2[i] == '0'; i--)
- tmp2[i] = '\0';
+ tmp2[i] = '\0';
if (tmp2[0] == '\0')
p->precision = 0;
}
/* calculate the padding. 1 for the dot */
p->width = p->width -
+ /* XXX - should this be d>0. && (p->flags & PF_PLUS) ? */
+#if 0
((d > 0. && p->justify == RIGHT) ? 1:0) -
+#else
+ ((d > 0. && (p->flags & PF_PLUS)) ? 1:0) -
+#endif
((p->flags & PF_SPACE) ? 1:0) -
strlen(tmp) - p->precision -
((p->precision != 0 || (p->flags & PF_ALTFORM)) ? 1 : 0); /* radix char */
- PAD_RIGHT(p);
- PUT_PLUS(d, p, 0.);
+
+ if (p->pad == ' ')
+ {
+ PAD_RIGHT(p);
+ PUT_PLUS(d, p, 0.);
+ }
+ else
+ {
+ if (*tmp == '-')
+ PUT_CHAR(*tmp++, p);
+ PUT_PLUS(d, p, 0.);
+ PAD_RIGHT(p);
+ }
PUT_SPACE(d, p, 0.);
while (*tmp)
@@ -1058,14 +1079,30 @@ exponent(p, d)
tmp = dtoa(d, p->precision, &tmp2);
/* 1 for unit, 1 for the '.', 1 for 'e|E',
- * 1 for '+|-', 2 for 'exp' */
+ * 1 for '+|-', 2 for 'exp' (but no `.' if precision == 0 */
/* calculate how much padding need */
p->width = p->width -
+ /* XXX - should this be d>0. && (p->flags & PF_PLUS) ? */
+#if 0
((d > 0. && p->justify == RIGHT) ? 1:0) -
- ((p->flags & PF_SPACE) ? 1:0) - p->precision - 6;
+#else
+ ((d > 0. && (p->flags & PF_PLUS)) ? 1:0) -
+#endif
+ (p->precision != 0 || (p->flags & PF_ALTFORM)) -
+ ((p->flags & PF_SPACE) ? 1:0) - p->precision - 5;
- PAD_RIGHT(p);
- PUT_PLUS(d, p, 0.);
+ if (p->pad == ' ')
+ {
+ PAD_RIGHT(p);
+ PUT_PLUS(d, p, 0.);
+ }
+ else
+ {
+ if (*tmp == '-')
+ PUT_CHAR(*tmp++, p);
+ PUT_PLUS(d, p, 0.);
+ PAD_RIGHT(p);
+ }
PUT_SPACE(d, p, 0.);
while (*tmp)
@@ -1163,7 +1200,7 @@ groupnum (s)
else if (*g == CHAR_MAX)
{
do
- *--re = *--se;
+ *--re = *--se;
while (se > s);
break;
}
@@ -1295,10 +1332,6 @@ vsnprintf_internal(data, string, length, format, args)
case '#':
data->flags |= PF_ALTFORM;
continue;
- case '0':
- data->flags |= PF_ZEROPAD;
- data->pad = '0';
- continue;
case '*':
if (data->flags & PF_DOT)
data->flags |= PF_STAR_P;
@@ -1322,13 +1355,25 @@ vsnprintf_internal(data, string, length, format, args)
if ((data->flags & PF_DOT) == 0)
{
data->flags |= PF_PLUS;
- data->justify = RIGHT;
+ if ((data->flags & PF_LADJUST) == 0)
+ data->justify = RIGHT;
}
continue;
case '\'':
data->flags |= PF_THOUSANDS;
continue;
+ case '0':
+ /* If we're not specifying precision (in which case we've seen
+ a `.') and we're not performing left-adjustment (in which
+ case the `0' is ignored), a `0' is taken as the zero-padding
+ flag. */
+ if ((data->flags & (PF_DOT|PF_LADJUST)) == 0)
+ {
+ data->flags |= PF_ZEROPAD;
+ data->pad = '0';
+ continue;
+ }
case '1': case '2': case '3':
case '4': case '5': case '6':
case '7': case '8': case '9':
@@ -1410,8 +1455,9 @@ conv_break:
else
{
/* reduce precision by 1 because of leading digit before
- decimal point in e format. */
- data->precision--;
+ decimal point in e format, unless specified as 0. */
+ if (data->precision > 0)
+ data->precision--;
exponent(data, d);
}
state = 0;
diff --git a/lib/sh/spell.c b/lib/sh/spell.c
index d0394c29..da78690c 100644
--- a/lib/sh/spell.c
+++ b/lib/sh/spell.c
@@ -30,7 +30,7 @@
#include <bashtypes.h>
#include <posixdir.h>
#include <posixstat.h>
-#ifndef _MINIX
+#if defined (HAVE_SYS_PARAM_H)
#include <sys/param.h>
#endif
diff --git a/lib/sh/strchrnul.c b/lib/sh/strchrnul.c
index 2e1608ec..00cb88c4 100644
--- a/lib/sh/strchrnul.c
+++ b/lib/sh/strchrnul.c
@@ -1,5 +1,5 @@
/* Searching in a string.
- Copyright (C) 2003, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+ Copyright (C) 2012 Free Software Foundation, Inc.
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
@@ -15,130 +15,21 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
+#include <stdio.h>
/* Specification. */
#include <string.h>
- /* On 32-bit hardware, choosing longword to be a 32-bit unsigned
- long instead of a 64-bit uintmax_t tends to give better
- performance. On 64-bit hardware, unsigned long is generally 64
- bits already. Change this typedef to experiment with
- performance. */
- typedef unsigned long int longword;
-
/* Find the first occurrence of C in S or the final NUL byte. */
char *
strchrnul (s, c_in)
const char *s;
int c_in;
{
- const unsigned char *char_ptr;
- const longword *longword_ptr;
- longword repeated_one;
- longword repeated_c;
- unsigned char c;
-
- c = (unsigned char) c_in;
- if (c == 0) /* find final null byte */
- return (char *)(s ? (s + strlen (s)) : s);
-
- /* Handle the first few bytes by reading one byte at a time.
- Do this until CHAR_PTR is aligned on a longword boundary. */
- for (char_ptr = (const unsigned char *) s;
- (size_t) char_ptr % sizeof (longword) != 0;
- ++char_ptr)
- if (!*char_ptr || *char_ptr == c)
- return (char *) char_ptr;
-
- longword_ptr = (const longword *) char_ptr;
-
- /* All these elucidatory comments refer to 4-byte longwords,
- but the theory applies equally well to any size longwords. */
-
- /* Compute auxiliary longword values:
- repeated_one is a value which has a 1 in every byte.
- repeated_c has c in every byte. */
- repeated_one = 0x01010101;
- repeated_c = c | (c << 8);
- repeated_c |= repeated_c << 16;
- if (0xffffffffU < (longword) -1)
- {
- repeated_one |= repeated_one << 31 << 1;
- repeated_c |= repeated_c << 31 << 1;
- if (8 < sizeof (longword))
- {
- size_t i;
-
- for (i = 64; i < sizeof (longword) * 8; i *= 2)
- {
- repeated_one |= repeated_one << i;
- repeated_c |= repeated_c << i;
- }
- }
- }
-
- /* Instead of the traditional loop which tests each byte, we will
- test a longword at a time. The tricky part is testing if *any of
- the four* bytes in the longword in question are equal to NUL or
- c. We first use an xor with repeated_c. This reduces the task
- to testing whether *any of the four* bytes in longword1 or
- longword2 is zero.
-
- Let's consider longword1. We compute tmp =
- ((longword1 - repeated_one) & ~longword1) & (repeated_one << 7).
- That is, we perform the following operations:
- 1. Subtract repeated_one.
- 2. & ~longword1.
- 3. & a mask consisting of 0x80 in every byte.
- Consider what happens in each byte:
- - If a byte of longword1 is zero, step 1 and 2 transform it into 0xff,
- and step 3 transforms it into 0x80. A carry can also be propagated
- to more significant bytes.
- - If a byte of longword1 is nonzero, let its lowest 1 bit be at
- position k (0 <= k <= 7); so the lowest k bits are 0. After step 1,
- the byte ends in a single bit of value 0 and k bits of value 1.
- After step 2, the result is just k bits of value 1: 2^k - 1. After
- step 3, the result is 0. And no carry is produced.
- So, if longword1 has only non-zero bytes, tmp is zero.
- Whereas if longword1 has a zero byte, call j the position of the least
- significant zero byte. Then the result has a zero at positions 0, ...,
- j-1 and a 0x80 at position j. We cannot predict the result at the more
- significant bytes (positions j+1..3), but it does not matter since we
- already have a non-zero bit at position 8*j+7.
-
- The test whether any byte in longword1 or longword2 is zero is equivalent
- to testing whether tmp1 is nonzero or tmp2 is nonzero. We can combine
- this into a single test, whether (tmp1 | tmp2) is nonzero.
-
- This test can read more than one byte beyond the end of a string,
- depending on where the terminating NUL is encountered. However,
- this is considered safe since the initialization phase ensured
- that the read will be aligned, therefore, the read will not cross
- page boundaries and will not cause a fault. */
-
- while (1)
- {
- longword longword1 = *longword_ptr ^ repeated_c;
- longword longword2 = *longword_ptr;
-
- if (((((longword1 - repeated_one) & ~longword1)
- | ((longword2 - repeated_one) & ~longword2))
- & (repeated_one << 7)) != 0)
- break;
- longword_ptr++;
- }
-
- char_ptr = (const unsigned char *) longword_ptr;
-
- /* At this point, we know that one of the sizeof (longword) bytes
- starting at char_ptr is == 0 or == c. On little-endian machines,
- we could determine the first such byte without any further memory
- accesses, just by looking at the tmp result from the last loop
- iteration. But this does not work on big-endian machines.
- Choose code that works in both cases. */
+ char c;
+ register char *s1;
- char_ptr = (unsigned char *) longword_ptr;
- while (*char_ptr && (*char_ptr != c))
- char_ptr++;
- return (char *) char_ptr;
+ for (c = c_in, s1 = (char *)s; s1 && *s1 && *s1 != c; s1++)
+ ;
+ return (s1);
}
diff --git a/lib/sh/strdup.c b/lib/sh/strdup.c
new file mode 100644
index 00000000..90fa3532
--- /dev/null
+++ b/lib/sh/strdup.c
@@ -0,0 +1,42 @@
+/* strdup - return a copy of a string in newly-allocated memory. */
+
+/* Copyright (C) 2013 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>
+
+/* Get specification. */
+#include <string.h>
+#include <stdlib.h>
+
+/* Duplicate S, returning an identical malloc'd string. */
+char *
+strdup (s)
+ const char *s;
+{
+ size_t len;
+ void *new;
+
+ len = strlen (s) + 1;
+ if ((new = malloc (len)) == NULL)
+ return NULL;
+
+ memcpy (new, s, len);
+ return ((char *)new);
+}
diff --git a/lib/sh/strerror.c b/lib/sh/strerror.c
index 4081e9c1..bf639263 100644
--- a/lib/sh/strerror.c
+++ b/lib/sh/strerror.c
@@ -23,7 +23,7 @@
#if !defined (HAVE_STRERROR)
#include <bashtypes.h>
-#ifndef _MINIX
+#if defined (HAVE_SYS_PARAM_H)
# include <sys/param.h>
#endif
diff --git a/lib/sh/strftime.c b/lib/sh/strftime.c
index aa3fc850..0ababc14 100644
--- a/lib/sh/strftime.c
+++ b/lib/sh/strftime.c
@@ -38,6 +38,7 @@
* Updated September, 2000
* Updated December, 2001
* Updated January, 2011
+ * Updated April, 2012
*
* Fixes from ado@elsie.nci.nih.gov,
* February 1991, May 1992
@@ -75,6 +76,7 @@
#define VMS_EXT 1 /* include %v for VMS date format */
#define HPUX_EXT 1 /* non-conflicting stuff in HP-UX date */
#define POSIX_SEMANTICS 1 /* call tzset() if TZ changes */
+#define POSIX_2008 1 /* flag and fw for C, F, G, Y formats */
#undef strchr /* avoid AIX weirdness */
@@ -96,27 +98,25 @@ static int iso8601wknum(const struct tm *timeptr);
#define range(low, item, hi) max(low, min(item, hi))
-#if !defined(OS2) && !defined(MSDOS) && defined(HAVE_TZNAME)
+/* Whew! This stuff is a mess. */
+#if !defined(OS2) && !defined(MSDOS) && !defined(__CYGWIN__) && defined(HAVE_TZNAME)
extern char *tzname[2];
extern int daylight;
#if defined(SOLARIS) || defined(mips) || defined (M_UNIX)
extern long int timezone, altzone;
#else
-# if defined (HPUX)
+# if defined (HPUX) || defined(__hpux)
extern long int timezone;
# else
+# if !defined(__CYGWIN__)
extern int timezone, altzone;
-# endif /* !HPUX */
-#endif /* !SOLARIS && !mips && !M_UNIX */
+# endif
+# endif
+#endif
#endif
#undef min /* just in case */
-/* format for %+ -- currently unused */
-#ifndef NATIONAL_FORMAT
-#define NATIONAL_FORMAT "%a %b %e %H:%M:%S %Z %Y"
-#endif
-
/* min --- return minimum of two numbers */
static inline int
@@ -135,6 +135,34 @@ max(int a, int b)
return (a > b ? a : b);
}
+#ifdef POSIX_2008
+/* iso_8601_2000_year --- format a year per ISO 8601:2000 as in 1003.1 */
+
+static void
+iso_8601_2000_year(char *buf, int year, size_t fw)
+{
+ int extra;
+ char sign = '\0';
+
+ if (year >= -9999 && year <= 9999) {
+ sprintf(buf, "%0*d", (int) fw, year);
+ return;
+ }
+
+ /* now things get weird */
+ if (year > 9999) {
+ sign = '+';
+ } else {
+ sign = '-';
+ year = -year;
+ }
+
+ extra = year / 10000;
+ year %= 10000;
+ sprintf(buf, "%c_%04d_%d", sign, extra, year);
+}
+#endif /* POSIX_2008 */
+
/* strftime --- produce formatted time */
size_t
@@ -155,12 +183,19 @@ strftime(char *s, size_t maxsize, const char *format, const struct tm *timeptr)
#ifndef HAVE_TM_ZONE
#ifndef HAVE_TM_NAME
#ifndef HAVE_TZNAME
+#ifndef __CYGWIN__
extern char *timezone();
struct timeval tv;
struct timezone zone;
+#endif /* __CYGWIN__ */
#endif /* HAVE_TZNAME */
#endif /* HAVE_TM_NAME */
#endif /* HAVE_TM_ZONE */
+#ifdef POSIX_2008
+ int pad;
+ size_t fw;
+ char flag;
+#endif /* POSIX_2008 */
/* various tables, useful in North America */
static const char *days_a[] = {
@@ -234,6 +269,40 @@ strftime(char *s, size_t maxsize, const char *format, const struct tm *timeptr)
*s++ = *format;
continue;
}
+#ifdef POSIX_2008
+ pad = '\0';
+ fw = 0;
+ flag = '\0';
+ switch (*++format) {
+ case '+':
+ flag = '+';
+ /* fall through */
+ case '0':
+ pad = '0';
+ format++;
+ break;
+
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ break;
+
+ default:
+ format--;
+ goto again;
+ }
+ for (; isdigit(*format); format++) {
+ fw = fw * 10 + (*format - '0');
+ }
+ format--;
+#endif /* POSIX_2008 */
+
again:
switch (*++format) {
case '\0':
@@ -285,8 +354,19 @@ strftime(char *s, size_t maxsize, const char *format, const struct tm *timeptr)
break;
case 'C':
+#ifdef POSIX_2008
+ if (pad != '\0' && fw > 0) {
+ size_t min_fw = (flag ? 3 : 2);
+
+ fw = max(fw, min_fw);
+ sprintf(tbuf, flag
+ ? "%+0*ld"
+ : "%0*ld", (int) fw,
+ (timeptr->tm_year + 1900L) / 100);
+ } else
+#endif /* POSIX_2008 */
century:
- sprintf(tbuf, "%02ld", (timeptr->tm_year + 1900L) / 100);
+ sprintf(tbuf, "%02ld", (timeptr->tm_year + 1900L) / 100);
break;
case 'd': /* day of the month, 01 - 31 */
@@ -307,7 +387,30 @@ strftime(char *s, size_t maxsize, const char *format, const struct tm *timeptr)
goto again;
case 'F': /* ISO 8601 date representation */
+ {
+#ifdef POSIX_2008
+ /*
+ * Field width for %F is for the whole thing.
+ * It must be at least 10.
+ */
+ char m_d[10];
+ strftime(m_d, sizeof m_d, "-%m-%d", timeptr);
+ size_t min_fw = 10;
+
+ if (pad != '\0' && fw > 0) {
+ fw = max(fw, min_fw);
+ } else {
+ fw = min_fw;
+ }
+
+ fw -= 6; /* -XX-XX at end are invariant */
+
+ iso_8601_2000_year(tbuf, timeptr->tm_year + 1900, fw);
+ strcat(tbuf, m_d);
+#else
strftime(tbuf, sizeof tbuf, "%Y-%m-%d", timeptr);
+#endif /* POSIX_2008 */
+ }
break;
case 'g':
@@ -329,8 +432,20 @@ strftime(char *s, size_t maxsize, const char *format, const struct tm *timeptr)
else
y = 1900L + timeptr->tm_year;
- if (*format == 'G')
- sprintf(tbuf, "%ld", y);
+ if (*format == 'G') {
+#ifdef POSIX_2008
+ if (pad != '\0' && fw > 0) {
+ size_t min_fw = 4;
+
+ fw = max(fw, min_fw);
+ sprintf(tbuf, flag
+ ? "%+0*ld"
+ : "%0*ld", (int) fw,
+ y);
+ } else
+#endif /* POSIX_2008 */
+ sprintf(tbuf, "%ld", y);
+ }
else
sprintf(tbuf, "%02ld", y % 100);
break;
@@ -455,7 +570,17 @@ strftime(char *s, size_t maxsize, const char *format, const struct tm *timeptr)
break;
case 'Y': /* year with century */
- fullyear:
+#ifdef POSIX_2008
+ if (pad != '\0' && fw > 0) {
+ size_t min_fw = 4;
+
+ fw = max(fw, min_fw);
+ sprintf(tbuf, flag
+ ? "%+0*ld"
+ : "%0*ld", (int) fw,
+ 1900L + timeptr->tm_year);
+ } else
+#endif /* POSIX_2008 */
sprintf(tbuf, "%ld", 1900L + timeptr->tm_year);
break;
@@ -496,12 +621,12 @@ strftime(char *s, size_t maxsize, const char *format, const struct tm *timeptr)
* Systems with tzname[] probably have timezone as
* secs west of GMT. Convert to mins east of GMT.
*/
-# ifdef HPUX
+# if defined(__hpux) || defined (HPUX) || defined(__CYGWIN__)
off = -timezone / 60;
# else
/* ADR: 4 August 2001, fixed this per gazelle@interaccess.com */
off = -(daylight ? altzone : timezone) / 60;
-# endif /* !HPUX */
+# endif
#else /* !HAVE_TZNAME */
gettimeofday(& tv, & zone);
off = -zone.tz_minuteswest;
diff --git a/lib/sh/stringvec.c b/lib/sh/stringvec.c
index b0ed4164..3bb4ab70 100644
--- a/lib/sh/stringvec.c
+++ b/lib/sh/stringvec.c
@@ -40,6 +40,14 @@ strvec_create (n)
return ((char **)xmalloc ((n) * sizeof (char *)));
}
+/* Allocate an array of strings with room for N members. */
+char **
+strvec_mcreate (n)
+ int n;
+{
+ return ((char **)malloc ((n) * sizeof (char *)));
+}
+
char **
strvec_resize (array, nsize)
char **array;
@@ -48,6 +56,14 @@ strvec_resize (array, nsize)
return ((char **)xrealloc (array, nsize * sizeof (char *)));
}
+char **
+strvec_mresize (array, nsize)
+ char **array;
+ int nsize;
+{
+ return ((char **)realloc (array, nsize * sizeof (char *)));
+}
+
/* Return the length of ARRAY, a NULL terminated array of char *. */
int
strvec_len (array)
diff --git a/lib/sh/strpbrk.c b/lib/sh/strpbrk.c
index 4439986a..8cce8308 100644
--- a/lib/sh/strpbrk.c
+++ b/lib/sh/strpbrk.c
@@ -29,7 +29,7 @@
#include <stdc.h>
-/* Find the first ocurrence in S of any character in ACCEPT. */
+/* Find the first occurrence in S of any character in ACCEPT. */
char *
strpbrk (s, accept)
register const char *s;
diff --git a/lib/sh/strtrans.c b/lib/sh/strtrans.c
index 2265782f..ae88e694 100644
--- a/lib/sh/strtrans.c
+++ b/lib/sh/strtrans.c
@@ -1,6 +1,6 @@
/* strtrans.c - Translate and untranslate strings with ANSI-C escape sequences. */
-/* Copyright (C) 2000-2010 Free Software Foundation, Inc.
+/* Copyright (C) 2000-2011 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -30,6 +30,9 @@
#include "shell.h"
+#include "shmbchar.h"
+#include "shmbutil.h"
+
#ifdef ESC
#undef ESC
#endif
@@ -74,7 +77,7 @@ ansicstr (string, len, flags, sawc, rlen)
case 'a': c = '\a'; break;
case 'v': c = '\v'; break;
#else
- case 'a': c = '\007'; break;
+ case 'a': c = (int) 0x07; break;
case 'v': c = (int) 0x0B; break;
#endif
case 'b': c = '\b'; break;
@@ -144,7 +147,7 @@ ansicstr (string, len, flags, sawc, rlen)
*r++ = '\\'; /* c remains unchanged */
break;
}
- else if (v <= UCHAR_MAX)
+ else if (v <= 0x7f) /* <= 0x7f translates directly */
{
c = v;
break;
@@ -208,6 +211,11 @@ ansic_quote (str, flags, rlen)
char *r, *ret, *s;
int l, rsize;
unsigned char c;
+ size_t clen;
+ int b;
+#if defined (HANDLE_MULTIBYTE)
+ wchar_t wc;
+#endif
if (str == 0 || *str == 0)
return ((char *)0);
@@ -219,10 +227,13 @@ ansic_quote (str, flags, rlen)
*r++ = '$';
*r++ = '\'';
- for (s = str, l = 0; *s; s++)
+ s = str;
+
+ for (s = str; c = *s; s++)
{
- c = *s;
- l = 1; /* 1 == add backslash; 0 == no backslash */
+ b = l = 1; /* 1 == add backslash; 0 == no backslash */
+ clen = 1;
+
switch (c)
{
case ESC: c = 'E'; break;
@@ -230,7 +241,7 @@ ansic_quote (str, flags, rlen)
case '\a': c = 'a'; break;
case '\v': c = 'v'; break;
#else
- case '\007': c = 'a'; break;
+ case 0x07: c = 'a'; break;
case 0x0b: c = 'v'; break;
#endif
@@ -243,7 +254,14 @@ ansic_quote (str, flags, rlen)
case '\'':
break;
default:
+#if defined (HANDLE_MULTIBYTE)
+ b = is_basic (c);
+ /* XXX - clen comparison to 0 is dicey */
+ if ((b == 0 && ((clen = mbrtowc (&wc, s, MB_CUR_MAX, 0)) < 0 || MB_INVALIDCH (clen) || iswprint (wc) == 0)) ||
+ (b == 1 && ISPRINT (c) == 0))
+#else
if (ISPRINT (c) == 0)
+#endif
{
*r++ = '\\';
*r++ = TOCHAR ((c >> 6) & 07);
@@ -254,9 +272,20 @@ ansic_quote (str, flags, rlen)
l = 0;
break;
}
+ if (b == 0 && clen == 0)
+ break;
+
if (l)
*r++ = '\\';
- *r++ = c;
+
+ if (clen == 1)
+ *r++ = c;
+ else
+ {
+ for (b = 0; b < (int)clen; b++)
+ *r++ = (unsigned char)s[b];
+ s += clen - 1; /* -1 because of the increment above */
+ }
}
*r++ = '\'';
@@ -266,6 +295,37 @@ ansic_quote (str, flags, rlen)
return ret;
}
+#if defined (HANDLE_MULTIBYTE)
+int
+ansic_wshouldquote (string)
+ const char *string;
+{
+ const wchar_t *wcs;
+ wchar_t wcc;
+
+ wchar_t *wcstr = NULL;
+ size_t slen;
+
+
+ slen = mbstowcs (wcstr, string, 0);
+
+ if (slen == -1)
+ slen = 0;
+ wcstr = (wchar_t *)xmalloc (sizeof (wchar_t) * (slen + 1));
+ mbstowcs (wcstr, string, slen + 1);
+
+ for (wcs = wcstr; wcc = *wcs; wcs++)
+ if (iswprint(wcc) == 0)
+ {
+ free (wcstr);
+ return 1;
+ }
+
+ free (wcstr);
+ return 0;
+}
+#endif
+
/* return 1 if we need to quote with $'...' because of non-printing chars. */
int
ansic_shouldquote (string)
@@ -278,8 +338,14 @@ ansic_shouldquote (string)
return 0;
for (s = string; c = *s; s++)
- if (ISPRINT (c) == 0)
- return 1;
+ {
+#if defined (HANDLE_MULTIBYTE)
+ if (is_basic (c) == 0)
+ return (ansic_wshouldquote (s));
+#endif
+ if (ISPRINT (c) == 0)
+ return 1;
+ }
return 0;
}
diff --git a/lib/sh/tmpfile.c b/lib/sh/tmpfile.c
index 0bbc2871..c06ad657 100644
--- a/lib/sh/tmpfile.c
+++ b/lib/sh/tmpfile.c
@@ -31,6 +31,8 @@
# include <unistd.h>
#endif
+#include <bashansi.h>
+
#include <stdio.h>
#include <errno.h>
@@ -135,7 +137,7 @@ sh_mktmpname (nameroot, flags)
filenum = (filenum << 1) ^
(unsigned long) time ((time_t *)0) ^
(unsigned long) dollar_dollar_pid ^
- (unsigned long) ((flags & MT_USERANDOM) ? get_random_number () : ntmpfiles++);
+ (unsigned long) ((flags & MT_USERANDOM) ? random () : ntmpfiles++);
sprintf (filename, "%s/%s-%lu", tdir, lroot, filenum);
if (tmpnamelen > 0 && tmpnamelen < 32)
filename[tdlen + 1 + tmpnamelen] = '\0';
@@ -184,7 +186,7 @@ sh_mktmpfd (nameroot, flags, namep)
filenum = (filenum << 1) ^
(unsigned long) time ((time_t *)0) ^
(unsigned long) dollar_dollar_pid ^
- (unsigned long) ((flags & MT_USERANDOM) ? get_random_number () : ntmpfiles++);
+ (unsigned long) ((flags & MT_USERANDOM) ? random () : ntmpfiles++);
sprintf (filename, "%s/%s-%lu", tdir, lroot, filenum);
if (tmpnamelen > 0 && tmpnamelen < 32)
filename[tdlen + 1 + tmpnamelen] = '\0';
diff --git a/lib/sh/unicode.c b/lib/sh/unicode.c
index d34fa08a..9ee7147d 100644
--- a/lib/sh/unicode.c
+++ b/lib/sh/unicode.c
@@ -1,6 +1,6 @@
/* unicode.c - functions to convert unicode characters */
-/* Copyright (C) 2010 Free Software Foundation, Inc.
+/* Copyright (C) 2010-2012 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -28,6 +28,7 @@
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
+#include <stdio.h>
#include <limits.h>
#if HAVE_ICONV
@@ -61,6 +62,8 @@ static iconv_t localconv;
#endif
#ifndef HAVE_LOCALE_CHARSET
+static char charsetbuf[40];
+
static char *
stub_charset ()
{
@@ -68,32 +71,46 @@ stub_charset ()
locale = get_locale_var ("LC_CTYPE");
if (locale == 0 || *locale == 0)
- return "ASCII";
+ {
+ strcpy (charsetbuf, "ASCII");
+ return charsetbuf;
+ }
s = strrchr (locale, '.');
if (s)
{
- t = strchr (s, '@');
+ strcpy (charsetbuf, s+1);
+ t = strchr (charsetbuf, '@');
if (t)
*t = 0;
- return ++s;
+ return charsetbuf;
}
- else if (STREQ (locale, "UTF-8"))
- return "UTF-8";
- else
- return "ASCII";
+ strcpy (charsetbuf, locale);
+ return charsetbuf;
}
#endif
+void
+u32reset ()
+{
+#if defined (HAVE_ICONV)
+ if (u32init && localconv != (iconv_t)-1)
+ {
+ iconv_close (localconv);
+ localconv = (iconv_t)-1;
+ }
+#endif
+ u32init = 0;
+ utf8locale = 0;
+}
+
/* u32toascii ? */
int
-u32tochar (wc, s)
- wchar_t wc;
+u32tochar (x, s)
+ unsigned long x;
char *s;
{
- unsigned long x;
int l;
- x = wc;
l = (x <= UCHAR_MAX) ? 1 : ((x <= USHORT_MAX) ? 2 : 4);
if (x <= UCHAR_MAX)
@@ -115,31 +132,107 @@ u32tochar (wc, s)
}
int
-u32toutf8 (wc, s)
- wchar_t wc;
+u32tocesc (wc, s)
+ u_bits32_t wc;
char *s;
{
int l;
- l = (wc < 0x0080) ? 1 : ((wc < 0x0800) ? 2 : 3);
+ if (wc < 0x10000)
+ l = sprintf (s, "\\u%04X", wc);
+ else
+ l = sprintf (s, "\\u%08X", wc);
+ return l;
+}
+
+/* Convert unsigned 32-bit int to utf-8 character string */
+int
+u32toutf8 (wc, s)
+ u_bits32_t wc;
+ char *s;
+{
+ int l;
if (wc < 0x0080)
- s[0] = (unsigned char)wc;
+ {
+ s[0] = (char)wc;
+ l = 1;
+ }
else if (wc < 0x0800)
{
s[0] = (wc >> 6) | 0xc0;
s[1] = (wc & 0x3f) | 0x80;
+ l = 2;
}
- else
+ else if (wc < 0x10000)
{
+ /* Technically, we could return 0 here if 0xd800 <= wc <= 0x0dfff */
s[0] = (wc >> 12) | 0xe0;
s[1] = ((wc >> 6) & 0x3f) | 0x80;
s[2] = (wc & 0x3f) | 0x80;
+ l = 3;
+ }
+ else if (wc < 0x200000)
+ {
+ s[0] = (wc >> 18) | 0xf0;
+ s[1] = ((wc >> 12) & 0x3f) | 0x80;
+ s[2] = ((wc >> 6) & 0x3f) | 0x80;
+ s[3] = (wc & 0x3f) | 0x80;
+ l = 4;
}
+ /* Strictly speaking, UTF-8 doesn't have characters longer than 4 bytes */
+ else if (wc < 0x04000000)
+ {
+ s[0] = (wc >> 24) | 0xf8;
+ s[1] = ((wc >> 18) & 0x3f) | 0x80;
+ s[2] = ((wc >> 12) & 0x3f) | 0x80;
+ s[3] = ((wc >> 6) & 0x3f) | 0x80;
+ s[4] = (wc & 0x3f) | 0x80;
+ l = 5;
+ }
+ else if (wc < 0x080000000)
+ {
+ s[0] = (wc >> 30) | 0xf8;
+ s[1] = ((wc >> 24) & 0x3f) | 0x80;
+ s[2] = ((wc >> 18) & 0x3f) | 0x80;
+ s[3] = ((wc >> 12) & 0x3f) | 0x80;
+ s[4] = ((wc >> 6) & 0x3f) | 0x80;
+ s[5] = (wc & 0x3f) | 0x80;
+ l = 6;
+ }
+ else
+ l = 0;
+
s[l] = '\0';
return l;
}
+/* Convert a 32-bit unsigned int (unicode) to a UTF-16 string. Rarely used,
+ only if sizeof(wchar_t) == 2. */
+int
+u32toutf16 (c, s)
+ u_bits32_t c;
+ unsigned short *s;
+{
+ int l;
+
+ l = 0;
+ if (c < 0x0d800)
+ {
+ s[0] = (unsigned short) (c & 0xFFFF);
+ l = 1;
+ }
+ else if (c >= 0x0e000 && c <= 0x010ffff)
+ {
+ c -= 0x010000;
+ s[0] = (unsigned short)((c >> 10) + 0xd800);
+ s[1] = (unsigned short)((c & 0x3ff) + 0xdc00);
+ l = 2;
+ }
+ s[l] = 0;
+ return l;
+}
+
/* convert a single unicode-32 character into a multibyte string and put the
result in S, which must be large enough (at least MB_LEN_MAX bytes) */
int
@@ -148,6 +241,7 @@ u32cconv (c, s)
char *s;
{
wchar_t wc;
+ wchar_t ws[3];
int n;
#if HAVE_ICONV
const char *charset;
@@ -157,21 +251,23 @@ u32cconv (c, s)
size_t sn;
#endif
- wc = c;
-
#if __STDC_ISO_10646__
- if (sizeof (wchar_t) == 4)
- {
- n = wctomb (s, wc);
- return n;
- }
+ wc = c;
+ if (sizeof (wchar_t) == 4 && c <= 0x7fffffff)
+ n = wctomb (s, wc);
+ else if (sizeof (wchar_t) == 2 && c <= 0x10ffff && u32toutf16 (c, ws))
+ n = wcstombs (s, ws, MB_LEN_MAX);
+ else
+ n = -1;
+ if (n != -1)
+ return n;
#endif
#if HAVE_NL_LANGINFO
codeset = nl_langinfo (CODESET);
if (STREQ (codeset, "UTF-8"))
{
- n = u32toutf8 (wc, s);
+ n = u32toutf8 (c, s);
return n;
}
#endif
@@ -191,25 +287,23 @@ u32cconv (c, s)
{
localconv = iconv_open (charset, "UTF-8");
if (localconv == (iconv_t)-1)
- localconv = iconv_open (charset, "ASCII");
+ /* We assume ASCII when presented with an unknown encoding. */
+ localconv = iconv_open ("ASCII", "UTF-8");
}
u32init = 1;
}
+ /* If we have a UTF-8 locale, convert to UTF-8 and return converted value. */
+ n = u32toutf8 (c, s);
if (utf8locale)
- {
- n = u32toutf8 (wc, s);
- return n;
- }
+ return n;
+ /* If the conversion is not supported, even the ASCII requested above, we
+ bail now. Currently we return the UTF-8 conversion. We could return
+ u32tocesc(). */
if (localconv == (iconv_t)-1)
- {
- n = u32tochar (wc, s);
- return n;
- }
-
- n = u32toutf8 (wc, s);
-
+ return n;
+
optr = obuf;
obytesleft = sizeof (obuf);
iptr = s;
@@ -218,7 +312,15 @@ u32cconv (c, s)
iconv (localconv, NULL, NULL, NULL, NULL);
if (iconv (localconv, (ICONV_CONST char **)&iptr, &sn, &optr, &obytesleft) == (size_t)-1)
- return n; /* You get utf-8 if iconv fails */
+ {
+#if 1
+ /* You get ISO C99 escape sequences if iconv fails */
+ n = u32tocesc (c, s);
+#else
+ /* You get UTF-8 if iconv fails */
+#endif
+ return n;
+ }
*optr = '\0';
@@ -226,10 +328,14 @@ u32cconv (c, s)
checking */
strcpy (s, obuf);
return (optr - obuf);
-#endif
+#endif /* HAVE_ICONV */
- n = u32tochar (wc, s); /* fallback */
+ n = u32tocesc (c, s); /* fallback is ISO C99 escape sequences */
return n;
}
-
+#else
+void
+u32reset ()
+{
+}
#endif /* HANDLE_MULTIBYTE */
diff --git a/lib/sh/wcsnwidth.c b/lib/sh/wcsnwidth.c
new file mode 100644
index 00000000..9c7e7cc5
--- /dev/null
+++ b/lib/sh/wcsnwidth.c
@@ -0,0 +1,56 @@
+/* wcsnwidth.c - compute display width of wide character string, up to max
+ specified width, return length. */
+
+/* Copyright (C) 2012 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>
+
+#if defined (HANDLE_MULTIBYTE)
+
+#include <stdc.h>
+#include <wchar.h>
+#include <bashansi.h>
+
+/* Return the number of wide characters that will be displayed from wide string
+ PWCS. If the display width exceeds MAX, return the number of wide chars
+ from PWCS required to display MAX characters on the screen. */
+int
+wcsnwidth(pwcs, n, max)
+ const wchar_t *pwcs;
+ size_t n, max;
+{
+ wchar_t wc, *ws;
+ int len, l;
+
+ len = 0;
+ ws = (wchar_t *)pwcs;
+ while (n-- > 0 && (wc = *ws++) != L'\0')
+ {
+ l = wcwidth (wc);
+ if (l < 0)
+ return (-1);
+ else if (l == max - len)
+ return (ws - pwcs);
+ else if (l > max - len)
+ return (--ws - pwcs);
+ len += l;
+ }
+ return (ws - pwcs);
+}
+#endif
diff --git a/lib/sh/zgetline.c b/lib/sh/zgetline.c
index 33ac830d..9cef9752 100644
--- a/lib/sh/zgetline.c
+++ b/lib/sh/zgetline.c
@@ -50,7 +50,7 @@ typedef ssize_t creadfunc_t __P((int, char *));
The differences are
(1) using file descriptor instead of FILE *,
(2) the order of arguments; the file descriptor comes the first, and
- (3) the addtion of thired argument, UNBUFFERED_READ; this argument
+ (3) the addition of third argument, UNBUFFERED_READ; this argument
controls whether get_line uses buffering or not to get a byte data
from FD. get_line uses zreadc if UNBUFFERED_READ is zero; and
uses zread if UNBUFFERED_READ is non-zero.
diff --git a/lib/sh/zmapfd.c b/lib/sh/zmapfd.c
index 4000c4a5..e7208921 100644
--- a/lib/sh/zmapfd.c
+++ b/lib/sh/zmapfd.c
@@ -66,11 +66,10 @@ zmapfd (fd, ostr, fn)
}
else if (nr < 0)
{
- rval = -1;
free (result);
if (ostr)
*ostr = (char *)NULL;
- break;
+ return -1;
}
RESIZE_MALLOCED_BUFFER (result, rind, nr, rsize, 128);
diff --git a/lib/sh/zread.c b/lib/sh/zread.c
index 5db21a98..868f9705 100644
--- a/lib/sh/zread.c
+++ b/lib/sh/zread.c
@@ -26,6 +26,7 @@
# include <unistd.h>
#endif
+#include <signal.h>
#include <errno.h>
#if !defined (errno)
@@ -36,6 +37,9 @@ extern int errno;
# define SEEK_CUR 1
#endif
+extern void check_signals_and_traps (void);
+extern int signal_is_trapped (int);
+
/* Read LEN bytes from FD into BUF. Retry the read on EINTR. Any other
error causes the loop to break. */
ssize_t
@@ -46,8 +50,22 @@ zread (fd, buf, len)
{
ssize_t r;
+#if 0
+#if defined (HAVE_SIGINTERRUPT)
+ if (signal_is_trapped (SIGCHLD))
+ siginterrupt (SIGCHLD, 1);
+#endif
+#endif
+
while ((r = read (fd, buf, len)) < 0 && errno == EINTR)
- ;
+ check_signals_and_traps (); /* XXX - should it be check_signals()? */
+
+#if 0
+#if defined (HAVE_SIGINTERRUPT)
+ siginterrupt (SIGCHLD, 0);
+#endif
+#endif
+
return r;
}
@@ -148,6 +166,34 @@ zreadcintr (fd, cp)
return 1;
}
+/* Like zreadc, but read a specified number of characters at a time. Used
+ for `read -N'. */
+ssize_t
+zreadn (fd, cp, len)
+ int fd;
+ char *cp;
+ size_t len;
+{
+ ssize_t nr;
+
+ if (lind == lused || lused == 0)
+ {
+ if (len > sizeof (lbuf))
+ len = sizeof (lbuf);
+ nr = zread (fd, lbuf, len);
+ lind = 0;
+ if (nr <= 0)
+ {
+ lused = 0;
+ return nr;
+ }
+ lused = nr;
+ }
+ if (cp)
+ *cp = lbuf[lind++];
+ return 1;
+}
+
void
zreset ()
{
diff --git a/lib/tilde/shell.c b/lib/tilde/shell.c
index 40a95b63..fafb8619 100644
--- a/lib/tilde/shell.c
+++ b/lib/tilde/shell.c
@@ -55,15 +55,26 @@ get_env_value (varname)
return ((char *)getenv (varname));
}
+/* If we're not using $HOME, assume that the passwd file information won't
+ change while this shell instance is running. */
char *
get_home_dir ()
{
- char *home_dir;
+ static char *home_dir = (char *)NULL;
struct passwd *entry;
- home_dir = (char *)NULL;
+ if (home_dir)
+ return (home_dir);
+
+#if defined (HAVE_GETPWUID)
entry = getpwuid (getuid ());
if (entry)
- home_dir = entry->pw_dir;
+ home_dir = savestring (entry->pw_dir);
+#endif
+
+#if defined (HAVE_GETPWENT)
+ endpwent (); /* some systems need this */
+#endif
+
return (home_dir);
}