summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/glob/glob.c208
-rw-r--r--lib/glob/glob.h11
-rw-r--r--lib/glob/glob_loop.c8
-rw-r--r--lib/glob/gmisc.c4
-rw-r--r--lib/glob/sm_loop.c55
-rw-r--r--lib/glob/smatch.c116
-rw-r--r--lib/glob/strmatch.c6
-rw-r--r--lib/glob/strmatch.h6
-rw-r--r--lib/glob/xmbsrtowcs.c118
-rw-r--r--lib/malloc/imalloc.h12
-rw-r--r--lib/malloc/malloc.c111
-rw-r--r--lib/malloc/mstats.h10
-rw-r--r--lib/malloc/shmalloc.h36
-rw-r--r--lib/malloc/stats.c8
-rw-r--r--lib/malloc/table.c12
-rw-r--r--lib/malloc/table.h20
-rw-r--r--lib/malloc/trace.c4
-rw-r--r--lib/malloc/watch.h4
-rw-r--r--lib/readline/bind.c256
-rw-r--r--lib/readline/colors.c11
-rw-r--r--lib/readline/complete.c104
-rw-r--r--lib/readline/display.c822
-rw-r--r--lib/readline/doc/history.texi2
-rw-r--r--lib/readline/doc/hstech.texi6
-rw-r--r--lib/readline/doc/hsuser.texi39
-rw-r--r--lib/readline/doc/rlman.texi2
-rw-r--r--lib/readline/doc/rltech.texi42
-rw-r--r--lib/readline/doc/rluser.texi79
-rw-r--r--lib/readline/doc/rluserman.texi2
-rw-r--r--lib/readline/doc/version.texi12
-rw-r--r--lib/readline/emacs_keymap.c4
-rw-r--r--lib/readline/examples/fileman.c6
-rw-r--r--lib/readline/examples/rltest.c1
-rw-r--r--lib/readline/funmap.c10
-rw-r--r--lib/readline/histexpand.c26
-rw-r--r--lib/readline/histfile.c54
-rw-r--r--lib/readline/input.c33
-rw-r--r--lib/readline/isearch.c75
-rw-r--r--lib/readline/kill.c110
-rw-r--r--lib/readline/mbutil.c106
-rw-r--r--lib/readline/misc.c63
-rw-r--r--lib/readline/posixdir.h2
-rw-r--r--lib/readline/posixstat.h22
-rw-r--r--lib/readline/readline.c98
-rw-r--r--lib/readline/readline.h16
-rw-r--r--lib/readline/rlmbutil.h2
-rw-r--r--lib/readline/rlprivate.h42
-rw-r--r--lib/readline/search.c47
-rw-r--r--lib/readline/signals.c87
-rw-r--r--lib/readline/terminal.c76
-rw-r--r--lib/readline/text.c105
-rw-r--r--lib/readline/tilde.c18
-rw-r--r--lib/readline/undo.c2
-rw-r--r--lib/readline/util.c3
-rw-r--r--lib/readline/vi_mode.c182
-rw-r--r--lib/sh/Makefile.in17
-rw-r--r--lib/sh/casemod.c4
-rw-r--r--lib/sh/eaccess.c12
-rw-r--r--lib/sh/fnxform.c12
-rw-r--r--lib/sh/fpurge.c4
-rw-r--r--lib/sh/gettimeofday.c35
-rw-r--r--lib/sh/input_avail.c73
-rw-r--r--lib/sh/mailstat.c2
-rw-r--r--lib/sh/makepath.c4
-rw-r--r--lib/sh/mktime.c18
-rw-r--r--lib/sh/netopen.c14
-rw-r--r--lib/sh/pathcanon.c2
-rw-r--r--lib/sh/pathphys.c4
-rw-r--r--lib/sh/random.c240
-rw-r--r--lib/sh/shmatch.c4
-rw-r--r--lib/sh/shquote.c77
-rw-r--r--lib/sh/snprintf.c42
-rw-r--r--lib/sh/spell.c6
-rw-r--r--lib/sh/strftime.c17
-rw-r--r--lib/sh/stringlist.c4
-rw-r--r--lib/sh/stringvec.c32
-rw-r--r--lib/sh/strtod.c8
-rw-r--r--lib/sh/strtoimax.c6
-rw-r--r--lib/sh/strtoumax.c6
-rw-r--r--lib/sh/strtrans.c24
-rw-r--r--lib/sh/times.c6
-rw-r--r--lib/sh/timeval.c27
-rw-r--r--lib/sh/tmpfile.c74
-rw-r--r--lib/sh/uconvert.c34
-rw-r--r--lib/sh/ufuncs.c15
-rw-r--r--lib/sh/unicode.c16
-rw-r--r--lib/sh/utf8.c71
-rw-r--r--lib/sh/winsize.c6
-rw-r--r--lib/sh/zcatfd.c12
-rw-r--r--lib/sh/zgetline.c14
-rw-r--r--lib/sh/zmapfd.c14
-rw-r--r--lib/sh/zread.c25
-rw-r--r--lib/tilde/tilde.c18
93 files changed, 3287 insertions, 1028 deletions
diff --git a/lib/glob/glob.c b/lib/glob/glob.c
index 398253b5..eb6277f0 100644
--- a/lib/glob/glob.c
+++ b/lib/glob/glob.c
@@ -1,6 +1,6 @@
/* glob.c -- file-name wildcard pattern matching for Bash.
- Copyright (C) 1985-2017 Free Software Foundation, Inc.
+ Copyright (C) 1985-2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne-Again SHell.
@@ -51,6 +51,7 @@
#include <signal.h>
#include "shell.h"
+#include "general.h"
#include "glob.h"
#include "strmatch.h"
@@ -83,11 +84,11 @@ struct globval
char *name;
};
-extern void throw_to_top_level __P((void));
-extern int sh_eaccess __P((const 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 void throw_to_top_level PARAMS((void));
+extern int sh_eaccess PARAMS((const char *, int));
+extern char *sh_makepath PARAMS((const char *, const char *, int));
+extern int signal_is_pending PARAMS((int));
+extern void run_pending_traps PARAMS((void));
extern int extended_glob;
@@ -99,34 +100,40 @@ int noglob_dot_filenames = 1;
is done without regard to case. */
int glob_ignore_case = 0;
+/* Global variable controlling whether globbing ever returns . or ..
+ regardless of the pattern. If set to 1, no glob pattern will ever
+ match `.' or `..'. Disabled by default. */
+int glob_always_skip_dot_and_dotdot = 0;
+
/* Global variable to return to signify an error in globbing. */
char *glob_error_return;
static struct globval finddirs_error_return;
/* Some forward declarations. */
-static int skipname __P((char *, char *, int));
+static int skipname PARAMS((char *, char *, int));
#if HANDLE_MULTIBYTE
-static int mbskipname __P((char *, char *, int));
+static int mbskipname PARAMS((char *, char *, int));
#endif
+void udequote_pathname PARAMS((char *));
#if HANDLE_MULTIBYTE
-static void udequote_pathname __P((char *));
-static void wdequote_pathname __P((char *));
+void wcdequote_pathname PARAMS((wchar_t *));
+static void wdequote_pathname PARAMS((char *));
#else
# define dequote_pathname udequote_pathname
#endif
-static void dequote_pathname __P((char *));
-static int glob_testdir __P((char *, int));
-static char **glob_dir_to_array __P((char *, char **, int));
+static void dequote_pathname PARAMS((char *));
+static int glob_testdir PARAMS((char *, int));
+static char **glob_dir_to_array PARAMS((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));
+extern char *glob_patscan PARAMS((char *, char *, int));
+extern wchar_t *glob_patscan_wc PARAMS((wchar_t *, wchar_t *, int));
/* And this from gmisc.c/gm_loop.c */
-extern int wextglob_pattern_p __P((wchar_t *));
+extern int wextglob_pattern_p PARAMS((wchar_t *));
-extern char *glob_dirscan __P((char *, int));
+extern char *glob_dirscan PARAMS((char *, int));
/* Compile `glob_loop.c' for single-byte characters. */
#define GCHAR unsigned char
@@ -159,7 +166,7 @@ glob_pattern_p (pattern)
wchar_t *wpattern;
int r;
- if (MB_CUR_MAX == 1)
+ if (MB_CUR_MAX == 1 || mbsmbchar (pattern) == 0)
return (internal_glob_pattern_p ((unsigned char *)pattern));
/* Convert strings to wide chars, and call the multibyte version. */
@@ -173,7 +180,7 @@ glob_pattern_p (pattern)
return r;
#else
- return (internal_glob_pattern_p (pattern));
+ return (internal_glob_pattern_p ((unsigned char *)pattern));
#endif
}
@@ -187,7 +194,7 @@ extglob_skipname (pat, dname, flags)
int flags;
{
char *pp, *pe, *t, *se;
- int n, r, negate, wild;
+ int n, r, negate, wild, nullpat;
negate = *pat == '!';
wild = *pat == '*' || *pat == '?';
@@ -214,6 +221,11 @@ extglob_skipname (pat, dname, flags)
return r;
}
+ /* Is the extglob pattern between the parens the null pattern? The null
+ pattern can match nothing, so should we check any remaining portion of
+ the pattern? */
+ nullpat = pe >= (pat + 2) && pe[-2] == '(' && pe[-1] == ')';
+
/* check every subpattern */
while (t = glob_patscan (pp, pe, '|'))
{
@@ -257,12 +269,14 @@ skipname (pat, dname, flags)
return (extglob_skipname (pat, dname, flags));
#endif
+ if (glob_always_skip_dot_and_dotdot && DOT_OR_DOTDOT (dname))
+ return 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[0] != '.' &&
(pat[0] != '\\' || pat[1] != '.') &&
- (dname[0] == '.' &&
- (dname[1] == '\0' || (dname[1] == '.' && dname[2] == '\0'))))
+ DOT_OR_DOTDOT (dname))
return 1;
/* If a dot must be explicitly matched, check to see if they do. */
@@ -280,12 +294,14 @@ wskipname (pat, dname, flags)
wchar_t *pat, *dname;
int flags;
{
+ if (glob_always_skip_dot_and_dotdot && WDOT_OR_DOTDOT (dname))
+ return 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[0] != L'.' &&
(pat[0] != L'\\' || pat[1] != L'.') &&
- (dname[0] == L'.' &&
- (dname[1] == L'\0' || (dname[1] == L'.' && dname[2] == L'\0'))))
+ WDOT_OR_DOTDOT (dname))
return 1;
/* If a leading dot must be explicitly matched, check to see if the
@@ -305,7 +321,7 @@ wextglob_skipname (pat, dname, flags)
{
#if EXTENDED_GLOB
wchar_t *pp, *pe, *t, n, *se;
- int r, negate, wild;
+ int r, negate, wild, nullpat;
negate = *pat == L'!';
wild = *pat == L'*' || *pat == L'?';
@@ -323,6 +339,11 @@ wextglob_skipname (pat, dname, flags)
return r;
}
+ /* Is the extglob pattern between the parens the null pattern? The null
+ pattern can match nothing, so should we check any remaining portion of
+ the pattern? */
+ nullpat = pe >= (pat + 2) && pe[-2] == L'(' && pe[-1] == L')';
+
/* check every subpattern */
while (t = glob_patscan_wc (pp, pe, '|'))
{
@@ -389,7 +410,7 @@ mbskipname (pat, dname, flags)
#endif /* HANDLE_MULTIBYTE */
/* Remove backslashes quoting characters in PATHNAME by modifying PATHNAME. */
-static void
+void
udequote_pathname (pathname)
char *pathname;
{
@@ -411,6 +432,26 @@ udequote_pathname (pathname)
#if HANDLE_MULTIBYTE
/* Remove backslashes quoting characters in PATHNAME by modifying PATHNAME. */
+void
+wcdequote_pathname (wpathname)
+ wchar_t *wpathname;
+{
+ int i, j;
+
+ for (i = j = 0; wpathname && wpathname[i]; )
+ {
+ if (wpathname[i] == L'\\')
+ i++;
+
+ wpathname[j++] = wpathname[i++];
+
+ if (wpathname[i - 1] == L'\0')
+ break;
+ }
+ if (wpathname)
+ wpathname[j] = L'\0';
+}
+
static void
wdequote_pathname (pathname)
char *pathname;
@@ -421,6 +462,12 @@ wdequote_pathname (pathname)
int i, j;
wchar_t *orig_wpathname;
+ if (mbsmbchar (pathname) == 0)
+ {
+ udequote_pathname (pathname);
+ return;
+ }
+
len = strlen (pathname);
/* Convert the strings into wide characters. */
n = xdupmbstowcs (&wpathname, NULL, pathname);
@@ -432,22 +479,17 @@ wdequote_pathname (pathname)
}
orig_wpathname = wpathname;
- for (i = j = 0; wpathname && wpathname[i]; )
- {
- if (wpathname[i] == L'\\')
- i++;
-
- wpathname[j++] = wpathname[i++];
-
- if (wpathname[i - 1] == L'\0')
- break;
- }
- if (wpathname)
- wpathname[j] = L'\0';
+ wcdequote_pathname (wpathname);
/* Convert the wide character string into unibyte character set. */
memset (&ps, '\0', sizeof(mbstate_t));
n = wcsrtombs(pathname, (const wchar_t **)&wpathname, len, &ps);
+ if (n == (size_t)-1 || (wpathname && *wpathname != 0)) /* what? now you tell me? */
+ {
+ wpathname = orig_wpathname;
+ memset (&ps, '\0', sizeof(mbstate_t));
+ n = xwcsrtombs (pathname, (const wchar_t **)&wpathname, len, &ps);
+ }
pathname[len] = '\0';
/* Can't just free wpathname here; wcsrtombs changes it in many cases. */
@@ -607,6 +649,7 @@ glob_vector (pat, dir, flags)
register unsigned int i;
int mflags; /* Flags passed to strmatch (). */
int pflags; /* flags passed to sh_makepath () */
+ int hasglob; /* return value from glob_pattern_p */
int nalloca;
struct globval *firstmalloc, *tmplink;
char *convfn;
@@ -648,10 +691,12 @@ glob_vector (pat, dir, flags)
patlen = (pat && *pat) ? strlen (pat) : 0;
/* If the filename pattern (PAT) does not contain any globbing characters,
+ or contains a pattern with only backslash escapes (hasglob == 2),
we can dispense with reading the directory, and just see if there is
a filename `DIR/PAT'. If there is, and we can access it, just make the
vector to return and bail immediately. */
- if (skip == 0 && glob_pattern_p (pat) == 0)
+ hasglob = 0;
+ if (skip == 0 && ((hasglob = glob_pattern_p (pat)) == 0 || hasglob == 2))
{
int dirlen;
struct stat finfo;
@@ -807,14 +852,6 @@ glob_vector (pat, dir, flags)
}
}
- /* When FLAGS includes GX_ALLDIRS, we want to skip a symlink
- to a directory, since we will pick the directory up later. */
- if (isdir == -2 && glob_testdir (subdir, 0) == 0)
- {
- free (subdir);
- continue;
- }
-
/* XXX - should we even add this if it's not a directory? */
nextlink = (struct globval *) malloc (sizeof (struct globval));
if (firstmalloc == 0)
@@ -1024,17 +1061,22 @@ glob_dir_to_array (dir, array, flags)
strcpy (result[i], dir);
if (add_slash)
result[i][l] = '/';
- strcpy (result[i] + l + add_slash, array[i]);
- if (flags & GX_MARKDIRS)
+ if (array[i][0])
{
- if ((stat (result[i], &sb) == 0) && S_ISDIR (sb.st_mode))
+ strcpy (result[i] + l + add_slash, array[i]);
+ if (flags & GX_MARKDIRS)
{
- size_t rlen;
- rlen = strlen (result[i]);
- result[i][rlen] = '/';
- result[i][rlen+1] = '\0';
+ if ((stat (result[i], &sb) == 0) && S_ISDIR (sb.st_mode))
+ {
+ size_t rlen;
+ rlen = strlen (result[i]);
+ result[i][rlen] = '/';
+ result[i][rlen+1] = '\0';
+ }
}
}
+ else
+ result[i][l+add_slash] = '\0';
}
result[i] = NULL;
@@ -1228,6 +1270,7 @@ glob_filename (pathname, flags)
files ending in `h' with a `/' appended. */
dname = directories[i];
dflags = flags & ~(GX_MARKDIRS|GX_ALLDIRS|GX_ADDCURDIR);
+ /* last_starstar? */
if ((flags & GX_GLOBSTAR) && filename[0] == '*' && filename[1] == '*' && filename[2] == '\0')
dflags |= GX_ALLDIRS|GX_ADDCURDIR;
if (dname[0] == '\0' && filename[0])
@@ -1235,7 +1278,44 @@ glob_filename (pathname, flags)
dflags |= GX_NULLDIR;
dname = "."; /* treat null directory name and non-null filename as current directory */
}
- temp_results = glob_vector (filename, dname, dflags);
+
+ /* Special handling for symlinks to directories with globstar on */
+ if (all_starstar && (dflags & GX_NULLDIR) == 0)
+ {
+ int dlen;
+
+ /* If we have a directory name that is not null (GX_NULLDIR above)
+ and is a symlink to a directory, we return the symlink if
+ we're not `descending' into it (filename[0] == 0) and return
+ glob_error_return (which causes the code below to skip the
+ name) otherwise. I should fold this into a test that does both
+ checks instead of calling stat twice. */
+ if (glob_testdir (dname, flags|GX_ALLDIRS) == -2 && glob_testdir (dname, 0) == 0)
+ {
+ if (filename[0] != 0)
+ temp_results = (char **)&glob_error_return; /* skip */
+ else
+ {
+ /* Construct array to pass to glob_dir_to_array */
+ temp_results = (char **)malloc (2 * sizeof (char *));
+ if (temp_results == NULL)
+ goto memory_error;
+ temp_results[0] = (char *)malloc (1);
+ if (temp_results[0] == 0)
+ {
+ free (temp_results);
+ goto memory_error;
+ }
+ **temp_results = '\0';
+ temp_results[1] = NULL;
+ dflags |= GX_SYMLINK; /* mostly for debugging */
+ }
+ }
+ else
+ temp_results = glob_vector (filename, dname, dflags);
+ }
+ else
+ temp_results = glob_vector (filename, dname, dflags);
/* Handle error cases. */
if (temp_results == NULL)
@@ -1283,6 +1363,8 @@ glob_filename (pathname, flags)
else
array = temp_results;
}
+ else if (dflags & GX_SYMLINK)
+ array = glob_dir_to_array (directories[i], temp_results, flags);
else
array = glob_dir_to_array (directories[i], temp_results, flags);
l = 0;
@@ -1347,7 +1429,21 @@ only_filename:
/* We could check whether or not the dequoted directory_name is a
directory and return it here, returning the original directory_name
- if not, but we don't do that yet. I'm not sure it matters. */
+ if not, but we don't do that. We do return the dequoted directory
+ name if we're not being called recursively and the dequoted name
+ corresponds to an actual directory. For better backwards compatibility,
+ we can return &glob_error_return unconditionally in this case. */
+
+ if (directory_len > 0 && hasglob == 2 && (flags & GX_RECURSE) == 0)
+ {
+ dequote_pathname (directory_name);
+ if (glob_testdir (directory_name, 0) < 0)
+ {
+ if (free_dirname)
+ free (directory_name);
+ return ((char **)&glob_error_return);
+ }
+ }
/* Handle GX_MARKDIRS here. */
result[0] = (char *) malloc (directory_len + 1);
diff --git a/lib/glob/glob.h b/lib/glob/glob.h
index 56ac08ba..ca3a66cf 100644
--- a/lib/glob/glob.h
+++ b/lib/glob/glob.h
@@ -1,5 +1,5 @@
/* File-name wildcard pattern matching for GNU.
- Copyright (C) 1985, 1988, 1989, 2008,2009 Free Software Foundation, Inc.
+ Copyright (C) 1985-2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne-Again SHell.
@@ -31,12 +31,13 @@
#define GX_ADDCURDIR 0x200 /* internal -- add passed directory name */
#define GX_GLOBSTAR 0x400 /* turn on special handling of ** */
#define GX_RECURSE 0x800 /* internal -- glob_filename called recursively */
+#define GX_SYMLINK 0x1000 /* internal -- symlink to a directory */
-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 glob_pattern_p PARAMS((const char *));
+extern char **glob_vector PARAMS((char *, char *, int));
+extern char **glob_filename PARAMS((char *, int));
-extern int extglob_pattern_p __P((const char *));
+extern int extglob_pattern_p PARAMS((const char *));
extern char *glob_error_return;
extern int noglob_dot_filenames;
diff --git a/lib/glob/glob_loop.c b/lib/glob/glob_loop.c
index 3a4f4f1e..467e7ae3 100644
--- a/lib/glob/glob_loop.c
+++ b/lib/glob/glob_loop.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2017 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -16,7 +16,7 @@
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
-static int INTERNAL_GLOB_PATTERN_P __P((const GCHAR *));
+static int INTERNAL_GLOB_PATTERN_P PARAMS((const GCHAR *));
/* Return nonzero if PATTERN has any special globbing chars in it.
Compiled twice, once each for single-byte and multibyte characters. */
@@ -70,7 +70,11 @@ INTERNAL_GLOB_PATTERN_P (pattern)
return 0;
}
+#if 0
return bsquote ? 2 : 0;
+#else
+ return (0);
+#endif
}
#undef INTERNAL_GLOB_PATTERN_P
diff --git a/lib/glob/gmisc.c b/lib/glob/gmisc.c
index a2bca965..f3d74cea 100644
--- a/lib/glob/gmisc.c
+++ b/lib/glob/gmisc.c
@@ -1,6 +1,6 @@
/* gmisc.c -- miscellaneous pattern matching utility functions for Bash.
- Copyright (C) 2010-2017 Free Software Foundation, Inc.
+ Copyright (C) 2010-2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne-Again SHell.
@@ -38,7 +38,7 @@
#include "glob.h"
/* Make sure these names continue to agree with what's in smatch.c */
-extern char *glob_patscan __P((char *, char *, int));
+extern char *glob_patscan PARAMS((char *, char *, int));
/* Compile `gm_loop.c' for single-byte characters. */
#define CHAR char
diff --git a/lib/glob/sm_loop.c b/lib/glob/sm_loop.c
index cc14fb16..a98c14bd 100644
--- a/lib/glob/sm_loop.c
+++ b/lib/glob/sm_loop.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -22,14 +22,16 @@ struct STRUCT
CHAR *string;
};
-int FCT __P((CHAR *, CHAR *, int));
+int FCT PARAMS((CHAR *, CHAR *, int));
-static int GMATCH __P((CHAR *, CHAR *, CHAR *, CHAR *, struct STRUCT *, 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 int GMATCH PARAMS((CHAR *, CHAR *, CHAR *, CHAR *, struct STRUCT *, int));
+static CHAR *PARSE_COLLSYM PARAMS((CHAR *, INT *));
+static CHAR *BRACKMATCH PARAMS((CHAR *, U_CHAR, int));
+static int EXTMATCH PARAMS((INT, CHAR *, CHAR *, CHAR *, CHAR *, int));
-/*static*/ CHAR *PATSCAN __P((CHAR *, CHAR *, INT));
+extern void DEQUOTE_PATHNAME PARAMS((CHAR *));
+
+/*static*/ CHAR *PATSCAN PARAMS((CHAR *, CHAR *, INT));
int
FCT (pattern, string, flags)
@@ -384,9 +386,10 @@ BRACKMATCH (p, test, flags)
{
register CHAR cstart, cend, c;
register int not; /* Nonzero if the sense of the character class is inverted. */
- int brcnt, brchr, forcecoll, isrange;
+ int brcnt, forcecoll, isrange;
INT pc;
CHAR *savep;
+ CHAR *brchrp;
U_CHAR orig_test;
orig_test = test;
@@ -455,6 +458,9 @@ BRACKMATCH (p, test, flags)
{
bcopy (p + 1, ccname, (close - p - 1) * sizeof (CHAR));
*(ccname + (close - p - 1)) = L('\0');
+ /* As a result of a POSIX discussion, char class names are
+ allowed to be quoted (?) */
+ DEQUOTE_PATHNAME (ccname);
pc = IS_CCLASS (orig_test, (XCHAR *)ccname);
}
if (pc == -1)
@@ -577,15 +583,10 @@ BRACKMATCH (p, test, flags)
isrange = 1;
}
-#if 0 /* TAG: bash-5.1 */
if (isrange == 0 && test == cstart)
goto matched;
if (isrange && RANGECMP (test, cstart, forcecoll) >= 0 && RANGECMP (test, cend, forcecoll) <= 0)
goto matched;
-#else
- if (RANGECMP (test, cstart, forcecoll) >= 0 && RANGECMP (test, cend, forcecoll) <= 0)
- goto matched;
-#endif
if (c == L(']'))
break;
@@ -597,7 +598,7 @@ matched:
/* Skip the rest of the [...] that already matched. */
c = *--p;
brcnt = 1;
- brchr = 0;
+ brchrp = 0;
while (brcnt > 0)
{
int oc;
@@ -611,13 +612,26 @@ matched:
if (c == L('[') && (*p == L('=') || *p == L(':') || *p == L('.')))
{
brcnt++;
- brchr = *p;
+ brchrp = p++; /* skip over the char after the left bracket */
+ if ((c = *p) == L('\0'))
+ return ((test == L('[')) ? savep : (CHAR *)0);
+ /* If *brchrp == ':' we should check that the rest of the characters
+ form a valid character class name. We don't do that yet, but we
+ keep BRCHRP in case we want to. */
+ }
+ /* We only want to check brchrp if we set it above. */
+ else if (c == L(']') && brcnt > 1 && brchrp != 0 && oc == *brchrp)
+ {
+ brcnt--;
+ brchrp = 0; /* just in case */
}
- /* we only want to check brchr if we set it above */
- else if (c == L(']') && brcnt > 1 && brchr != 0 && oc == brchr)
- brcnt--;
- else if (c == L(']') && brcnt == 1)
- brcnt--;
+ /* Left bracket loses its special meaning inside a bracket expression.
+ It is only valid when followed by a `.', `=', or `:', which we check
+ for above. Technically the right bracket can appear in a collating
+ symbol, so we check for that here. Otherwise, it terminates the
+ bracket expression. */
+ else if (c == L(']') && (brchrp == 0 || *brchrp != L('.')) && brcnt >= 1)
+ brcnt = 0;
else if (!(flags & FNM_NOESCAPE) && c == L('\\'))
{
if (*p == '\0')
@@ -915,6 +929,7 @@ fprintf(stderr, "extmatch: flags = %d\n", flags);
#undef PATSCAN
#undef STRCOMPARE
#undef EXTMATCH
+#undef DEQUOTE_PATHNAME
#undef STRUCT
#undef BRACKMATCH
#undef STRCHR
diff --git a/lib/glob/smatch.c b/lib/glob/smatch.c
index 64fdbbb7..a58456d7 100644
--- a/lib/glob/smatch.c
+++ b/lib/glob/smatch.c
@@ -1,7 +1,7 @@
/* strmatch.c -- ksh-like extended pattern matching for the shell and filename
globbing. */
-/* Copyright (C) 1991-2017 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -36,6 +36,12 @@
extern int errno;
#endif
+#if FNMATCH_EQUIV_FALLBACK
+/* We don't include <fnmatch.h> in order to avoid namespace collisions; the
+ internal strmatch still uses the FNM_ constants. */
+extern int fnmatch (const char *, const char *, int);
+#endif
+
/* First, compile `sm_loop.c' for single-byte characters. */
#define CHAR unsigned char
#define U_CHAR unsigned char
@@ -55,6 +61,32 @@ extern int errno;
int glob_asciirange = GLOBASCII_DEFAULT;
+#if FNMATCH_EQUIV_FALLBACK
+/* Construct a string w1 = "c1" and a pattern w2 = "[[=c2=]]" and pass them
+ to fnmatch to see if wide characters c1 and c2 collate as members of the
+ same equivalence class. We can't really do this portably any other way */
+static int
+_fnmatch_fallback (s, p)
+ int s, p; /* string char, patchar */
+{
+ char s1[2]; /* string */
+ char s2[8]; /* constructed pattern */
+
+ s1[0] = (unsigned char)s;
+ s1[1] = '\0';
+
+ /* reconstruct the pattern */
+ s2[0] = s2[1] = '[';
+ s2[2] = '=';
+ s2[3] = (unsigned char)p;
+ s2[4] = '=';
+ s2[5] = s2[6] = ']';
+ s2[7] = '\0';
+
+ return (fnmatch ((const char *)s2, (const char *)s1, 0));
+}
+#endif
+
/* 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
@@ -63,9 +95,11 @@ int glob_asciirange = GLOBASCII_DEFAULT;
straight ordering as if in the C locale. */
#if defined (HAVE_STRCOLL)
-/* Helper function for collating symbol equivalence. */
+/* Helper functions for collating symbol equivalence. */
+
+/* Return 0 if C1 == C2 or collates equally if FORCECOLL is non-zero. */
static int
-rangecmp (c1, c2, forcecoll)
+charcmp (c1, c2, forcecoll)
int c1, c2;
int forcecoll;
{
@@ -86,8 +120,21 @@ rangecmp (c1, c2, forcecoll)
s1[0] = c1;
s2[0] = c2;
- if ((ret = strcoll (s1, s2)) != 0)
- return ret;
+ return (strcoll (s1, s2));
+}
+
+static int
+rangecmp (c1, c2, forcecoll)
+ int c1, c2;
+ int forcecoll;
+{
+ int r;
+
+ r = charcmp (c1, c2, forcecoll);
+
+ /* We impose a total ordering here by returning c1-c2 if charcmp returns 0 */
+ if (r != 0)
+ return r;
return (c1 - c2); /* impose total ordering */
}
#else /* !HAVE_STRCOLL */
@@ -95,14 +142,23 @@ rangecmp (c1, c2, forcecoll)
#endif /* !HAVE_STRCOLL */
#if defined (HAVE_STRCOLL)
+/* Returns 1 if chars C and EQUIV collate equally in the current locale. */
static int
-collequiv (c1, c2)
- int c1, c2;
+collequiv (c, equiv)
+ int c, equiv;
{
- return (rangecmp (c1, c2, 1) == 0);
+ if (charcmp (c, equiv, 1) == 0)
+ return 1;
+
+#if FNMATCH_EQUIV_FALLBACK
+ return (_fnmatch_fallback (c, equiv) == 0);
+#else
+ return 0;
+#endif
+
}
#else
-# define collequiv(c1, c2) ((c1) == (c2))
+# define collequiv(c, equiv) ((c) == (equiv))
#endif
#define _COLLSYM _collsym
@@ -260,6 +316,7 @@ is_cclass (c, name)
#define PATSCAN glob_patscan
#define STRCOMPARE strcompare
#define EXTMATCH extmatch
+#define DEQUOTE_PATHNAME udequote_pathname
#define STRUCT smat_struct
#define STRCHR(S, C) strchr((S), (C))
#define MEMCHR(S, C, N) memchr((S), (C), (N))
@@ -286,13 +343,9 @@ is_cclass (c, name)
# define STREQ(s1, s2) ((wcscmp (s1, s2) == 0))
# define STREQN(a, b, n) ((a)[0] == (b)[0] && wcsncmp(a, b, n) == 0)
-extern char *mbsmbchar __P((const char *));
+extern char *mbsmbchar PARAMS((const char *));
#if FNMATCH_EQUIV_FALLBACK
-/* We don't include <fnmatch.h> in order to avoid namespace collisions; the
- internal strmatch still uses the FNM_ constants. */
-extern int fnmatch (const char *, const char *, int);
-
/* Construct a string w1 = "c1" and a pattern w2 = "[[=c2=]]" and pass them
to fnmatch to see if wide characters c1 and c2 collate as members of the
same equivalence class. We can't really do this portably any other way */
@@ -324,13 +377,13 @@ _fnmatch_fallback_wc (c1, c2)
#endif
static int
-rangecmp_wc (c1, c2, forcecoll)
+charcmp_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' };
- int r, oerrno;
+ int r;
if (c1 == c2)
return 0;
@@ -341,27 +394,35 @@ rangecmp_wc (c1, c2, forcecoll)
s1[0] = c1;
s2[0] = c2;
-#if 0 /* TAG:bash-5.1 */
- /* We impose a total ordering here by returning c1-c2 if wcscoll returns 0,
- as we do above in the single-byte case. If we do this, we can no longer
- use this code in collequiv_wc */
- if ((r = wcscoll (s1, s2)) != 0)
+ return (wcscoll (s1, s2));
+}
+
+static int
+rangecmp_wc (c1, c2, forcecoll)
+ wint_t c1, c2;
+ int forcecoll;
+{
+ int r;
+
+ r = charcmp_wc (c1, c2, forcecoll);
+
+ /* We impose a total ordering here by returning c1-c2 if charcmp returns 0,
+ as we do above in the single-byte case. */
+ if (r != 0 || forcecoll)
return r;
return ((int)(c1 - c2)); /* impose total ordering */
-#else
- return (wcscoll (s1, s2));
-#endif
}
-/* Returns non-zero on success */
+/* Returns 1 if wide chars C and EQUIV collate equally in the current locale. */
static int
collequiv_wc (c, equiv)
wint_t c, equiv;
{
wchar_t s, p;
- if (rangecmp_wc (c, equiv, 1) == 0)
+ if (charcmp_wc (c, equiv, 1) == 0)
return 1;
+
#if FNMATCH_EQUIV_FALLBACK
/* We check explicitly for success (fnmatch returns 0) to avoid problems if
our local definition of FNM_NOMATCH (strmatch.h) doesn't match the
@@ -500,6 +561,7 @@ posix_cclass_only (pattern)
#define PATSCAN glob_patscan_wc
#define STRCOMPARE wscompare
#define EXTMATCH extmatch_wc
+#define DEQUOTE_PATHNAME wcdequote_pathname
#define STRUCT wcsmat_struct
#define STRCHR(S, C) wcschr((S), (C))
#define MEMCHR(S, C, N) wmemchr((S), (C), (N))
@@ -529,7 +591,7 @@ xstrmatch (pattern, string, flags)
if (MB_CUR_MAX == 1)
return (internal_strmatch ((unsigned char *)pattern, (unsigned char *)string, flags));
- if (mbsmbchar (string) == 0 && mbsmbchar (pattern) == 0 && posix_cclass_only (pattern) )
+ if (mbsmbchar (string) == 0 && mbsmbchar (pattern) == 0 && posix_cclass_only (pattern))
return (internal_strmatch ((unsigned char *)pattern, (unsigned char *)string, flags));
n = xdupmbstowcs (&wpattern, NULL, pattern);
diff --git a/lib/glob/strmatch.c b/lib/glob/strmatch.c
index cea9bd86..5b7b49fb 100644
--- a/lib/glob/strmatch.c
+++ b/lib/glob/strmatch.c
@@ -1,7 +1,7 @@
/* strmatch.c -- ksh-like extended pattern matching for the shell and filename
globbing. */
-/* Copyright (C) 1991-2002 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -24,9 +24,9 @@
#include "stdc.h"
#include "strmatch.h"
-extern int xstrmatch __P((char *, char *, int));
+extern int xstrmatch PARAMS((char *, char *, int));
#if defined (HANDLE_MULTIBYTE)
-extern int internal_wstrmatch __P((wchar_t *, wchar_t *, int));
+extern int internal_wstrmatch PARAMS((wchar_t *, wchar_t *, int));
#endif
int
diff --git a/lib/glob/strmatch.h b/lib/glob/strmatch.h
index aee00cc8..fa7be7bb 100644
--- a/lib/glob/strmatch.h
+++ b/lib/glob/strmatch.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2004 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne-Again SHell.
@@ -55,10 +55,10 @@
/* Match STRING against the filename pattern PATTERN,
returning zero if it matches, FNM_NOMATCH if not. */
-extern int strmatch __P((char *, char *, int));
+extern int strmatch PARAMS((char *, char *, int));
#if HANDLE_MULTIBYTE
-extern int wcsmatch __P((wchar_t *, wchar_t *, int));
+extern int wcsmatch PARAMS((wchar_t *, wchar_t *, int));
#endif
#endif /* _STRMATCH_H */
diff --git a/lib/glob/xmbsrtowcs.c b/lib/glob/xmbsrtowcs.c
index 11a4d1b9..17250c30 100644
--- a/lib/glob/xmbsrtowcs.c
+++ b/lib/glob/xmbsrtowcs.c
@@ -1,6 +1,6 @@
/* xmbsrtowcs.c -- replacement function for mbsrtowcs */
-/* Copyright (C) 2002-2013 Free Software Foundation, Inc.
+/* Copyright (C) 2002-2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -35,6 +35,11 @@
#if HANDLE_MULTIBYTE
+#include <errno.h>
+#if !defined (errno)
+extern int errno;
+#endif
+
#define WSBUF_INC 32
#ifndef FREE
@@ -42,7 +47,7 @@
#endif
#if ! HAVE_STRCHRNUL
-extern char *strchrnul __P((const char *, int));
+extern char *strchrnul PARAMS((const char *, int));
#endif
/* On some locales (ex. ja_JP.sjis), mbsrtowc doesn't convert 0x5c to U<0x5c>.
@@ -406,4 +411,113 @@ xdupmbstowcs (destp, indicesp, src)
return (wcnum - 1);
}
+/* Convert wide character string to multibyte character string. Treat invalid
+ wide characters as bytes. Used only in unusual circumstances.
+
+ Written by Bruno Haible <bruno@clisp.org>, 2008, adapted by Chet Ramey
+ for use in Bash. */
+
+/* Convert wide character string *SRCP to a multibyte character string and
+ store the result in DEST. Store at most LEN bytes in DEST. */
+size_t
+xwcsrtombs (char *dest, const wchar_t **srcp, size_t len, mbstate_t *ps)
+{
+ const wchar_t *src;
+ size_t cur_max; /* XXX - locale_cur_max */
+ char buf[64], *destptr, *tmp_dest;
+ unsigned char uc;
+ mbstate_t prev_state;
+
+ cur_max = MB_CUR_MAX;
+ if (cur_max > sizeof (buf)) /* Holy cow. */
+ return (size_t)-1;
+
+ src = *srcp;
+
+ if (dest != NULL)
+ {
+ destptr = dest;
+
+ for (; len > 0; src++)
+ {
+ wchar_t wc;
+ size_t ret;
+
+ wc = *src;
+ /* If we have room, store directly into DEST. */
+ tmp_dest = destptr;
+ ret = wcrtomb (len >= cur_max ? destptr : buf, wc, ps);
+
+ if (ret == (size_t)(-1)) /* XXX */
+ {
+ /* Since this is used for globbing and other uses of filenames,
+ treat invalid wide character sequences as bytes. This is
+ intended to be symmetric with xdupmbstowcs2. */
+handle_byte:
+ destptr = tmp_dest; /* in case wcrtomb modified it */
+ uc = wc;
+ ret = 1;
+ if (len >= cur_max)
+ *destptr = uc;
+ else
+ buf[0] = uc;
+ if (ps)
+ memset (ps, 0, sizeof (mbstate_t));
+ }
+
+ if (ret > cur_max) /* Holy cow */
+ goto bad_input;
+
+ if (len < ret)
+ break;
+
+ if (len < cur_max)
+ memcpy (destptr, buf, ret);
+
+ if (wc == 0)
+ {
+ src = NULL;
+ /* Here mbsinit (ps). */
+ break;
+ }
+ destptr += ret;
+ len -= ret;
+ }
+ *srcp = src;
+ return destptr - dest;
+ }
+ else
+ {
+ /* Ignore dest and len, don't store *srcp at the end, and
+ don't clobber *ps. */
+ mbstate_t state = *ps;
+ size_t totalcount = 0;
+
+ for (;; src++)
+ {
+ wchar_t wc;
+ size_t ret;
+
+ wc = *src;
+ ret = wcrtomb (buf, wc, &state);
+
+ if (ret == (size_t)(-1))
+ goto bad_input2;
+ if (wc == 0)
+ {
+ /* Here mbsinit (&state). */
+ break;
+ }
+ totalcount += ret;
+ }
+ return totalcount;
+ }
+
+bad_input:
+ *srcp = src;
+bad_input2:
+ errno = EILSEQ;
+ return (size_t)(-1);
+}
+
#endif /* HANDLE_MULTIBYTE */
diff --git a/lib/malloc/imalloc.h b/lib/malloc/imalloc.h
index 82b09eba..d07adac2 100644
--- a/lib/malloc/imalloc.h
+++ b/lib/malloc/imalloc.h
@@ -1,6 +1,6 @@
/* imalloc.h -- internal malloc definitions shared by source files. */
-/* Copyright (C) 2001-2003 Free Software Foundation, Inc.
+/* Copyright (C) 2001-2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -67,11 +67,11 @@
# endif /* HAVE_BCOPY */
#endif /* !__GNUC__ */
-#if !defined (__P)
+#if !defined (PARAMS)
# if defined (__STDC__) || defined (__GNUC__) || defined (__cplusplus) || defined (PROTOTYPES)
-# define __P(protos) protos
+# define PARAMS(protos) protos
# else
-# define __P(protos) ()
+# define PARAMS(protos) ()
# endif
#endif
@@ -167,7 +167,7 @@ do { \
#include <signal.h>
-extern void _malloc_block_signals __P((sigset_t *, sigset_t *));
-extern void _malloc_unblock_signals __P((sigset_t *, sigset_t *));
+extern void _malloc_block_signals PARAMS((sigset_t *, sigset_t *));
+extern void _malloc_unblock_signals PARAMS((sigset_t *, sigset_t *));
#endif /* _IMALLOC_H */
diff --git a/lib/malloc/malloc.c b/lib/malloc/malloc.c
index 5621adf4..439f8ef1 100644
--- a/lib/malloc/malloc.c
+++ b/lib/malloc/malloc.c
@@ -1,6 +1,6 @@
/* malloc.c - dynamic memory allocation for bash. */
-/* Copyright (C) 1985-2005 Free Software Foundation, Inc.
+/* Copyright (C) 1985-2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne-Again SHell.
@@ -25,6 +25,8 @@
*
* Nov 1983, Mike@BRL, Added support for 4.1C/4.2 BSD.
*
+ * [VERY] old explanation:
+ *
* This is a very fast storage allocator. It allocates blocks of a small
* number of different sizes, and keeps free lists of each size. Blocks
* that don't exactly fit are passed up to the next larger size. In this
@@ -84,6 +86,10 @@
#include <errno.h>
#include <stdio.h>
+#if !defined (botch)
+#include <stdlib.h>
+#endif
+
#if defined (HAVE_MMAP)
#include <sys/mman.h>
#endif
@@ -134,22 +140,35 @@
enough room in the block for the new size. Range checking is always
done. */
union mhead {
+#if SIZEOF_CHAR_P == 8
+ bits64_t mh_align[2]; /* 16 */
+#else
bits64_t mh_align; /* 8 */
+#endif
struct {
char mi_alloc; /* ISALLOC or ISFREE */ /* 1 */
char mi_index; /* index in nextf[] */ /* 1 */
/* Remainder are valid only when block is allocated */
u_bits16_t mi_magic2; /* should be == MAGIC2 */ /* 2 */
u_bits32_t mi_nbytes; /* # of bytes allocated */ /* 4 */
+#if SIZEOF_CHAR_P == 8
+ char mi_magic8[8]; /* MAGIC1 guard bytes */ /* 8 */
+#endif
} minfo;
};
#define mh_alloc minfo.mi_alloc
#define mh_index minfo.mi_index
#define mh_nbytes minfo.mi_nbytes
#define mh_magic2 minfo.mi_magic2
+#define mh_magic8 minfo.mi_magic8
#define MOVERHEAD sizeof(union mhead)
+
+#if SIZEOF_CHAR_P == 8
+#define MALIGN_MASK 15
+#else
#define MALIGN_MASK 7 /* one less than desired alignment */
+#endif
typedef union _malloc_guard {
char s[4];
@@ -163,6 +182,8 @@ typedef union _malloc_guard {
to describe the overhead for when the block is in use,
and we do not want the free-list pointer to count in that. */
+/* If SIZEOF_CHAR_P == 8, this goes into the mh_magic8 buffer at the end of
+ the rest of the struct. This may need adjusting. */
#define CHAIN(a) \
(*(union mhead **) (sizeof (char *) + (char *) (a)))
@@ -170,13 +191,14 @@ typedef union _malloc_guard {
and end of each allocated block, and make sure they are undisturbed
whenever a free or a realloc occurs. */
-/* Written in the 2 bytes before the block's real space (-4 bytes) */
+/* Written in the bytes before the block's real space (-SIZEOF_CHAR_P bytes) */
+#define MAGIC1 0x55
#define MAGIC2 0x5555
#define MSLOP 4 /* 4 bytes extra for u_bits32_t size */
/* How many bytes are actually allocated for a request of size N --
- rounded up to nearest multiple of 8 after accounting for malloc
- overhead. */
+ rounded up to nearest multiple of 2*SIZEOF_CHAR_P after accounting for
+ malloc overhead. */
#define ALLOCATED_BYTES(n) \
(((n) + MOVERHEAD + MSLOP + MALIGN_MASK) & ~MALIGN_MASK)
@@ -204,12 +226,12 @@ typedef union _malloc_guard {
/* Should we use mmap for large allocations? */
#if defined (HAVE_MMAP)
-# if !defined (MAP_ANON) && defined (MAP_ANONYMOUS)
-# define MAP_ANON MAP_ANONYMOUS
+# if defined (MAP_ANON) && !defined (MAP_ANONYMOUS)
+# define MAP_ANONYMOUS MAP_ANON
# endif
#endif
-#if defined (HAVE_MMAP) && defined (MAP_ANON)
+#if defined (HAVE_MMAP) && defined (MAP_ANONYMOUS)
# define USE_MMAP
#endif
@@ -273,32 +295,32 @@ extern int errno;
#endif
/* Declarations for internal functions */
-static PTR_T internal_malloc __P((size_t, const char *, int, int));
-static PTR_T internal_realloc __P((PTR_T, size_t, const char *, int, int));
-static void internal_free __P((PTR_T, const char *, int, int));
-static PTR_T internal_memalign __P((size_t, size_t, const char *, int, int));
+static PTR_T internal_malloc PARAMS((size_t, const char *, int, int));
+static PTR_T internal_realloc PARAMS((PTR_T, size_t, const char *, int, int));
+static void internal_free PARAMS((PTR_T, const char *, int, int));
+static PTR_T internal_memalign PARAMS((size_t, size_t, const char *, int, int));
#ifndef NO_CALLOC
-static PTR_T internal_calloc __P((size_t, size_t, const char *, int, int));
-static void internal_cfree __P((PTR_T, const char *, int, int));
+static PTR_T internal_calloc PARAMS((size_t, size_t, const char *, int, int));
+static void internal_cfree PARAMS((PTR_T, const char *, int, int));
#endif
#ifndef NO_VALLOC
-static PTR_T internal_valloc __P((size_t, const char *, int, int));
+static PTR_T internal_valloc PARAMS((size_t, const char *, int, int));
#endif
#if defined (botch)
extern void botch ();
#else
-static void botch __P((const char *, const char *, int));
+static void botch PARAMS((const char *, const char *, int));
#endif
-static void xbotch __P((PTR_T, int, const char *, const char *, int));
+static void xbotch PARAMS((PTR_T, int, const char *, const char *, int));
#if !HAVE_DECL_SBRK
extern char *sbrk ();
#endif /* !HAVE_DECL_SBRK */
#ifdef SHELL
-extern int interrupt_immediately, running_trap;
-extern int signal_is_trapped __P((int));
+extern int running_trap;
+extern int signal_is_trapped PARAMS((int));
#endif
#ifdef MALLOC_STATS
@@ -317,8 +339,8 @@ int malloc_mmap_threshold = MMAP_THRESHOLD;
char _malloc_trace_buckets[NBUCKETS];
/* These should really go into a header file. */
-extern void mtrace_alloc __P((const char *, PTR_T, size_t, const char *, int));
-extern void mtrace_free __P((PTR_T, int, const char *, int));
+extern void mtrace_alloc PARAMS((const char *, PTR_T, size_t, const char *, int));
+extern void mtrace_free PARAMS((PTR_T, int, const char *, int));
#endif
#if !defined (botch)
@@ -598,9 +620,9 @@ morecore (nu)
blocked_sigs = 0;
#ifdef SHELL
# if defined (SIGCHLD)
- if (interrupt_immediately || running_trap || signal_is_trapped (SIGINT) || signal_is_trapped (SIGCHLD))
+ if (running_trap || signal_is_trapped (SIGINT) || signal_is_trapped (SIGCHLD))
# else
- if (interrupt_immediately || running_trap || signal_is_trapped (SIGINT))
+ if (running_trap || signal_is_trapped (SIGINT))
# endif
#endif
{
@@ -689,7 +711,7 @@ morecore (nu)
memtop += sbrk_amt;
- /* shouldn't happen, but just in case -- require 8-byte alignment */
+ /* shouldn't happen, but just in case -- require 8- or 16-byte alignment */
if ((long)mp & MALIGN_MASK)
{
mp = (union mhead *) (((long)mp + MALIGN_MASK) & ~MALIGN_MASK);
@@ -719,8 +741,13 @@ malloc_debug_dummy ()
write (1, "malloc_debug_dummy\n", 19);
}
+#if SIZEOF_CHAR_P == 8
+#define PREPOP_BIN 3
+#define PREPOP_SIZE 64
+#else
#define PREPOP_BIN 2
#define PREPOP_SIZE 32
+#endif
static int
pagealign ()
@@ -756,8 +783,8 @@ pagealign ()
memtop += sbrk_needed;
/* Take the memory which would otherwise be wasted and populate the most
- popular bin (2 == 32 bytes) with it. Add whatever we need to curbrk
- to make things 32-byte aligned, compute how many 32-byte chunks we're
+ popular bin (3 == 64 bytes) with it. Add whatever we need to curbrk
+ to make things 64-byte aligned, compute how many 64-byte chunks we're
going to get, and set up the bin. */
curbrk += sbrk_needed & (PREPOP_SIZE - 1);
sbrk_needed -= sbrk_needed & (PREPOP_SIZE - 1);
@@ -818,7 +845,7 @@ internal_malloc (n, file, line, flags) /* get a block */
if (nbytes <= binsize(nunits))
break;
- /* Silently reject too-large requests. */
+ /* Silently reject too-large requests. XXX - can increase this if HAVE_MMAP */
if (nunits >= NBUCKETS)
return ((PTR_T) NULL);
@@ -859,6 +886,11 @@ internal_malloc (n, file, line, flags) /* get a block */
p->mh_magic2 = MAGIC2;
p->mh_nbytes = n;
+#if SIZEOF_CHAR_P == 8
+ /* Begin guard */
+ MALLOC_MEMSET ((char *)p->mh_magic8, MAGIC1, 8);
+#endif
+
/* End guard */
mg.i = n;
z = mg.s;
@@ -893,6 +925,14 @@ internal_malloc (n, file, line, flags) /* get a block */
_malloc_ckwatch (p + 1, file, line, W_ALLOC, n);
#endif
+#if defined (MALLOC_DEBUG)
+ z = (char *) (p + 1);
+ /* Check alignment of returned pointer */
+ if ((unsigned long)z & MALIGN_MASK)
+ fprintf (stderr, "malloc: %s:%d: warning: request for %d bytes not aligned on %d byte boundary\r\n",
+ file ? file : _("unknown"), line, p->mh_nbytes, MALIGN_MASK+1);
+#endif
+
return (PTR_T) (p + 1);
}
@@ -952,6 +992,15 @@ internal_free (mem, file, line, flags)
if (IN_BUCKET(nbytes, nunits) == 0)
xbotch (mem, ERR_UNDERFLOW,
_("free: underflow detected; mh_nbytes out of range"), file, line);
+#if SIZEOF_CHAR_P == 8
+ {
+ int i;
+ for (i = 0, z = p->mh_magic8; i < 8; i++)
+ if (*z++ != MAGIC1)
+ xbotch (mem, ERR_UNDERFLOW,
+ _("free: underflow detected; magic8 corrupted"), file, line);
+ }
+#endif
ap += p->mh_nbytes;
z = mg.s;
@@ -1083,6 +1132,16 @@ internal_realloc (mem, n, file, line, flags)
if (IN_BUCKET(nbytes, nunits) == 0)
xbotch (mem, ERR_UNDERFLOW,
_("realloc: underflow detected; mh_nbytes out of range"), file, line);
+#if SIZEOF_CHAR_P == 8
+ {
+ int i;
+ for (i = 0, z = p->mh_magic8; i < 8; i++)
+ if (*z++ != MAGIC1)
+ xbotch (mem, ERR_UNDERFLOW,
+ _("realloc: underflow detected; magic8 corrupted"), file, line);
+
+ }
+#endif
m = (char *)mem + (tocopy = p->mh_nbytes);
z = mg.s;
diff --git a/lib/malloc/mstats.h b/lib/malloc/mstats.h
index dac02980..ce8aaeca 100644
--- a/lib/malloc/mstats.h
+++ b/lib/malloc/mstats.h
@@ -1,6 +1,6 @@
/* mstats.h - definitions for malloc statistics */
-/* Copyright (C) 2001-2003 Free Software Foundation, Inc.
+/* Copyright (C) 2001-2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne-Again SHell.
@@ -104,10 +104,10 @@ struct bucket_stats {
int nmmap; /* currently unused */
};
-extern struct bucket_stats malloc_bucket_stats __P((int));
-extern struct _malstats malloc_stats __P((void));
-extern void print_malloc_stats __P((char *));
-extern void trace_malloc_stats __P((char *, char *));
+extern struct bucket_stats malloc_bucket_stats PARAMS((int));
+extern struct _malstats malloc_stats PARAMS((void));
+extern void print_malloc_stats PARAMS((char *));
+extern void trace_malloc_stats PARAMS((char *, char *));
#endif /* MALLOC_STATS */
diff --git a/lib/malloc/shmalloc.h b/lib/malloc/shmalloc.h
index 2dac6154..d51193eb 100644
--- a/lib/malloc/shmalloc.h
+++ b/lib/malloc/shmalloc.h
@@ -1,6 +1,6 @@
/* Functions (currently) for use by the shell to do malloc debugging and
tracking. */
-/* Copyright (C) 2001-2003 Free Software Foundation, Inc.
+/* Copyright (C) 2001-2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne-Again SHell.
@@ -21,11 +21,11 @@
#ifndef _SH_MALLOC_H
#define _SH_MALLOC_H
-#ifndef __P
+#ifndef PARAMS
# if defined (__STDC__) || defined (__GNUC__) || defined (__cplusplus)
-# define __P(protos) protos
+# define PARAMS(protos) protos
# else
-# define __P(protos) ()
+# define PARAMS(protos) ()
# endif
#endif
@@ -41,30 +41,30 @@
#endif /* PTR_T */
-extern PTR_T sh_malloc __P((size_t, const char *, int));
-extern PTR_T sh_realloc __P((PTR_T, size_t, const char *, int));
-extern void sh_free __P((PTR_T, const char *, int));
+extern PTR_T sh_malloc PARAMS((size_t, const char *, int));
+extern PTR_T sh_realloc PARAMS((PTR_T, size_t, const char *, int));
+extern void sh_free PARAMS((PTR_T, const char *, int));
-extern PTR_T sh_memalign __P((size_t, size_t, const char *, int));
+extern PTR_T sh_memalign PARAMS((size_t, size_t, const char *, int));
-extern PTR_T sh_calloc __P((size_t, size_t, const char *, int));
-extern void sh_cfree __P((PTR_T, const char *, int));
+extern PTR_T sh_calloc PARAMS((size_t, size_t, const char *, int));
+extern void sh_cfree PARAMS((PTR_T, const char *, int));
-extern PTR_T sh_valloc __P((size_t, const char *, int));
+extern PTR_T sh_valloc PARAMS((size_t, const char *, int));
/* trace.c */
-extern int malloc_set_trace __P((int));
+extern int malloc_set_trace PARAMS((int));
extern void malloc_set_tracefp (); /* full prototype requires stdio.h */
-extern void malloc_set_tracefn __P((char *, char *));
+extern void malloc_set_tracefn PARAMS((char *, char *));
/* table.c */
-extern void mregister_dump_table __P((void));
-extern void mregister_table_init __P((void));
-extern int malloc_set_register __P((int));
+extern void mregister_dump_table PARAMS((void));
+extern void mregister_table_init PARAMS((void));
+extern int malloc_set_register PARAMS((int));
/* stats.c */
-extern void print_malloc_stats __P((char *));
+extern void print_malloc_stats PARAMS((char *));
extern void fprint_malloc_stats (); /* full prototype requires stdio.h */
-extern void trace_malloc_stats __P((char *, char *));
+extern void trace_malloc_stats PARAMS((char *, char *));
#endif
diff --git a/lib/malloc/stats.c b/lib/malloc/stats.c
index 05247970..b38df9f4 100644
--- a/lib/malloc/stats.c
+++ b/lib/malloc/stats.c
@@ -1,6 +1,6 @@
/* stats.c - malloc statistics */
-/* Copyright (C) 2001-2003 Free Software Foundation, Inc.
+/* Copyright (C) 2001-2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne-Again SHell.
@@ -34,13 +34,13 @@
#include "mstats.h"
-extern int malloc_free_blocks __P((int));
+extern int malloc_free_blocks PARAMS((int));
extern int malloc_mmap_threshold;
extern struct _malstats _mstats;
-extern FILE *_imalloc_fopen __P((char *, char *, char *, char *, size_t));
+extern FILE *_imalloc_fopen PARAMS((char *, char *, char *, char *, size_t));
struct bucket_stats
malloc_bucket_stats (size)
@@ -110,7 +110,7 @@ _print_malloc_stats (s, fp)
if (i == malloc_mmap_threshold+1)
fprintf (fp, "--------\n");
if (v.nmal > 0)
- fprintf (fp, "%8lu\t%4d\t%6d\t%5d\t%8d\t%8d %5d %8d\n", (unsigned long)v.blocksize, v.nfree, v.nused, v.nmal, v.nmorecore, v.nlesscore, v.nsplit, v.ncoalesce);
+ fprintf (fp, "%8lu\t%4d\t%6d\t%5d%8d\t%8d %5d %8d\n", (unsigned long)v.blocksize, v.nfree, v.nused, v.nmal, v.nmorecore, v.nlesscore, v.nsplit, v.ncoalesce);
totfree += v.nfree * v.blocksize;
totused += v.nused * v.blocksize;
}
diff --git a/lib/malloc/table.c b/lib/malloc/table.c
index 97946dc7..e6acbf4a 100644
--- a/lib/malloc/table.c
+++ b/lib/malloc/table.c
@@ -1,6 +1,6 @@
/* table.c - bookkeeping functions for allocated memory */
-/* Copyright (C) 2001-2003 Free Software Foundation, Inc.
+/* Copyright (C) 2001-2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -29,15 +29,15 @@
#include "table.h"
#ifdef SHELL
-extern int interrupt_immediately, running_trap;
-extern int signal_is_trapped __P((int));
+extern int running_trap;
+extern int signal_is_trapped PARAMS((int));
#endif
extern int malloc_register;
#ifdef MALLOC_REGISTER
-extern FILE *_imalloc_fopen __P((char *, char *, char *, char *, size_t));
+extern FILE *_imalloc_fopen PARAMS((char *, char *, char *, char *, size_t));
#define FIND_ALLOC 0x01 /* find slot for new allocation */
#define FIND_EXIST 0x02 /* find slot for existing entry for free() or search */
@@ -174,7 +174,7 @@ mregister_alloc (tag, mem, size, file, line)
/* 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))
+ if (running_trap || signal_is_trapped (SIGINT) || signal_is_trapped (SIGCHLD))
#endif
{
_malloc_block_signals (&set, &oset);
@@ -229,7 +229,7 @@ mregister_free (mem, size, file, line)
/* 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))
+ if (running_trap || signal_is_trapped (SIGINT) || signal_is_trapped (SIGCHLD))
#endif
{
_malloc_block_signals (&set, &oset);
diff --git a/lib/malloc/table.h b/lib/malloc/table.h
index 7494f0a5..92866cf2 100644
--- a/lib/malloc/table.h
+++ b/lib/malloc/table.h
@@ -1,6 +1,6 @@
/* table.h - definitions for tables for keeping track of allocated memory */
-/* Copyright (C) 2001-2003 Free Software Foundation, Inc.
+/* Copyright (C) 2001-2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne-Again SHell.
@@ -57,12 +57,12 @@ typedef struct mr_table {
#define REG_TABLE_SIZE 8192
-extern mr_table_t *mr_table_entry __P((PTR_T));
-extern void mregister_alloc __P((const char *, PTR_T, size_t, const char *, int));
-extern void mregister_free __P((PTR_T, int, const char *, int));
+extern mr_table_t *mr_table_entry PARAMS((PTR_T));
+extern void mregister_alloc PARAMS((const char *, PTR_T, size_t, const char *, int));
+extern void mregister_free PARAMS((PTR_T, int, const char *, int));
extern void mregister_describe_mem ();
-extern void mregister_dump_table __P((void));
-extern void mregister_table_init __P((void));
+extern void mregister_dump_table PARAMS((void));
+extern void mregister_table_init PARAMS((void));
typedef struct ma_table {
const char *file;
@@ -70,10 +70,10 @@ typedef struct ma_table {
int nalloc;
} ma_table_t;
-extern void mlocation_register_alloc __P((const char *, int));
-extern void mlocation_table_init __P((void));
-extern void mlocation_dump_table __P((void));
-extern void mlocation_write_table __P((void));
+extern void mlocation_register_alloc PARAMS((const char *, int));
+extern void mlocation_table_init PARAMS((void));
+extern void mlocation_dump_table PARAMS((void));
+extern void mlocation_write_table PARAMS((void));
/* NOTE: HASH_MIX taken from dmalloc (http://dmalloc.com) */
diff --git a/lib/malloc/trace.c b/lib/malloc/trace.c
index 95898b70..391ca9d8 100644
--- a/lib/malloc/trace.c
+++ b/lib/malloc/trace.c
@@ -1,6 +1,6 @@
/* trace.c - tracing functions for malloc */
-/* Copyright (C) 2001-2003 Free Software Foundation, Inc.
+/* Copyright (C) 2001-2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -35,7 +35,7 @@ static int _mtrace_verbose = 0;
#ifdef MALLOC_TRACE
-extern FILE *_imalloc_fopen __P((char *, char *, char *, char *, size_t));
+extern FILE *_imalloc_fopen PARAMS((char *, char *, char *, char *, size_t));
FILE *_mtrace_fp = NULL;
extern char _malloc_trace_buckets[];
diff --git a/lib/malloc/watch.h b/lib/malloc/watch.h
index 6782acc4..2a0f4970 100644
--- a/lib/malloc/watch.h
+++ b/lib/malloc/watch.h
@@ -1,6 +1,6 @@
/* watch.h - definitions for tables for keeping track of allocated memory */
-/* Copyright (C) 2001-2003 Free Software Foundation, Inc.
+/* Copyright (C) 2001-2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne-Again SHell.
@@ -34,7 +34,7 @@
extern int _malloc_nwatch;
-extern void _malloc_ckwatch __P((PTR_T, const char *, int, int, unsigned long));
+extern void _malloc_ckwatch PARAMS((PTR_T, const char *, int, int, unsigned long));
#endif /* MALLOC_WATCH */
diff --git a/lib/readline/bind.c b/lib/readline/bind.c
index 57ae10f7..87596dce 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-2017 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2020 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.
@@ -135,12 +135,13 @@ rl_add_defun (const char *name, rl_command_func_t *function, int key)
int
rl_bind_key (int key, rl_command_func_t *function)
{
- char keyseq[3];
+ char keyseq[4];
int l;
- if (key < 0)
+ if (key < 0 || key > largest_char)
return (key);
+ /* Want to make this a multi-character key sequence with an ESC prefix */
if (META_CHAR (key) && _rl_convert_meta_chars_to_ascii)
{
if (_rl_keymap[ESC].type == ISKMAP)
@@ -153,24 +154,43 @@ rl_bind_key (int key, rl_command_func_t *function)
escmap[key].function = function;
return (0);
}
- return (key);
+
+ /* Otherwise, let's just let rl_generic_bind handle the key sequence.
+ We start it off with ESC here and let the code below add the rest
+ of the sequence. */
+ keyseq[0] = ESC;
+ l = 1;
+ key = UNMETA(key);
+ goto bind_keyseq;
}
/* If it's bound to a function or macro, just overwrite. Otherwise we have
to treat it as a key sequence so rl_generic_bind handles shadow keymaps
- for us. If we are binding '\' make sure to escape it so it makes it
- through the call to rl_translate_keyseq. */
+ for us. If we are binding '\' or \C-@ (NUL) make sure to escape it so
+ it makes it through the call to rl_translate_keyseq. */
if (_rl_keymap[key].type != ISKMAP)
{
+ if (_rl_keymap[key].type == ISMACR)
+ xfree ((char *)_rl_keymap[key].function);
_rl_keymap[key].type = ISFUNC;
_rl_keymap[key].function = function;
}
else
{
l = 0;
+bind_keyseq:
if (key == '\\')
- keyseq[l++] = '\\';
- keyseq[l++] = key;
+ {
+ keyseq[l++] = '\\';
+ keyseq[l++] = '\\';
+ }
+ else if (key == '\0')
+ {
+ keyseq[l++] = '\\';
+ keyseq[l++] = '0';
+ }
+ else
+ keyseq[l++] = key;
keyseq[l] = '\0';
rl_bind_keyseq (keyseq, function);
}
@@ -242,6 +262,13 @@ rl_unbind_function_in_map (rl_command_func_t *func, Keymap map)
map[i].function = (rl_command_func_t *)NULL;
rval = 1;
}
+ else if (map[i].type == ISKMAP) /* TAG:readline-8.1 */
+ {
+ int r;
+ r = rl_unbind_function_in_map (func, FUNCTION_TO_KEYMAP (map, i));
+ if (r == 1)
+ rval = 1;
+ }
}
return rval;
}
@@ -352,7 +379,7 @@ int
rl_generic_bind (int type, const char *keyseq, char *data, Keymap map)
{
char *keys;
- int keys_len, prevkey;
+ int keys_len, prevkey, ic;
register int i;
KEYMAP_ENTRY k;
Keymap prevmap;
@@ -385,7 +412,6 @@ rl_generic_bind (int type, const char *keyseq, char *data, Keymap map)
for (i = 0; i < keys_len; i++)
{
unsigned char uc = keys[i];
- int ic;
if (i > 0)
prevkey = ic;
@@ -397,6 +423,9 @@ rl_generic_bind (int type, const char *keyseq, char *data, Keymap map)
return -1;
}
+ /* We now rely on rl_translate_keyseq to do this conversion, so this
+ check is superfluous. */
+#if 0
if (META_CHAR (ic) && _rl_convert_meta_chars_to_ascii)
{
ic = UNMETA (ic);
@@ -406,6 +435,7 @@ rl_generic_bind (int type, const char *keyseq, char *data, Keymap map)
map = FUNCTION_TO_KEYMAP (map, ESC);
}
}
+#endif
if ((i + 1) < keys_len)
{
@@ -439,9 +469,7 @@ rl_generic_bind (int type, const char *keyseq, char *data, Keymap map)
}
else
{
- if (map[ic].type == ISMACR)
- xfree ((char *)map[ic].function);
- else if (map[ic].type == ISKMAP)
+ if (map[ic].type == ISKMAP)
{
prevmap = map;
map = FUNCTION_TO_KEYMAP (map, ic);
@@ -454,6 +482,8 @@ rl_generic_bind (int type, const char *keyseq, char *data, Keymap map)
if (type == ISFUNC && data == 0)
data = (char *)_rl_null_function;
}
+ if (map[ic].type == ISMACR)
+ xfree ((char *)map[ic].function);
map[ic].function = KEYMAP_TO_FUNCTION (data);
map[ic].type = type;
@@ -492,59 +522,38 @@ rl_generic_bind (int type, const char *keyseq, char *data, Keymap map)
int
rl_translate_keyseq (const char *seq, char *array, int *len)
{
- register int i, c, l, temp;
+ register int i, l, temp;
+ int has_control, has_meta;
+ unsigned char c;
- for (i = l = 0; c = seq[i]; i++)
+ has_control = 0;
+ has_meta = 0;
+
+ /* When there are incomplete prefixes \C- or \M- (has_control || has_meta)
+ without base character at the end of SEQ, they are processed as the
+ prefixes for '\0'.
+ */
+ for (i = l = 0; (c = seq[i]) || has_control || has_meta; i++)
{
- if (c == '\\')
+ /* Only backslashes followed by a non-null character are handled
+ specially. Trailing backslash (backslash followed by '\0') is
+ processed as a normal character.
+ */
+ if (c == '\\' && seq[i + 1] != '\0')
{
c = seq[++i];
- if (c == 0)
+ /* Handle \C- and \M- prefixes. */
+ if (c == 'C' && seq[i + 1] == '-')
{
- array[l++] = '\\'; /* preserve trailing backslash */
- break;
+ i++;
+ has_control = 1;
+ continue;
}
-
- /* Handle \C- and \M- prefixes. */
- if ((c == 'C' || c == 'M') && seq[i + 1] == '-')
+ else if (c == 'M' && seq[i + 1] == '-')
{
- /* Handle special case of backwards define. */
- if (strncmp (&seq[i], "C-\\M-", 5) == 0)
- {
- array[l++] = ESC; /* ESC is meta-prefix */
- i += 5;
- array[l++] = CTRL (_rl_to_upper (seq[i]));
- }
- else if (c == 'M')
- {
- i++; /* seq[i] == '-' */
- /* XXX - obey convert-meta setting */
- if (_rl_convert_meta_chars_to_ascii && _rl_keymap[ESC].type == ISKMAP)
- array[l++] = ESC; /* ESC is meta-prefix */
- else if (seq[i+1] == '\\' && seq[i+2] == 'C' && seq[i+3] == '-')
- {
- i += 4;
- temp = (seq[i] == '?') ? RUBOUT : CTRL (_rl_to_upper (seq[i]));
- array[l++] = META (temp);
- }
- else
- {
- /* This doesn't yet handle things like \M-\a, which may
- or may not have any reasonable meaning. You're
- probably better off using straight octal or hex. */
- i++;
- array[l++] = META (seq[i]);
- }
- }
- else if (c == 'C')
- {
- i += 2;
- /* Special hack for C-?... */
- array[l++] = (seq[i] == '?') ? RUBOUT : CTRL (_rl_to_upper (seq[i]));
- }
- if (seq[i] == '\0')
- break;
+ i++;
+ has_meta = 1;
continue;
}
@@ -555,34 +564,34 @@ rl_translate_keyseq (const char *seq, char *array, int *len)
switch (c)
{
case 'a':
- array[l++] = '\007';
+ c = '\007';
break;
case 'b':
- array[l++] = '\b';
+ c = '\b';
break;
case 'd':
- array[l++] = RUBOUT; /* readline-specific */
+ c = RUBOUT; /* readline-specific */
break;
case 'e':
- array[l++] = ESC;
+ c = ESC;
break;
case 'f':
- array[l++] = '\f';
+ c = '\f';
break;
case 'n':
- array[l++] = NEWLINE;
+ c = NEWLINE;
break;
case 'r':
- array[l++] = RETURN;
+ c = RETURN;
break;
case 't':
- array[l++] = TAB;
+ c = TAB;
break;
case 'v':
- array[l++] = 0x0B;
+ c = 0x0B;
break;
case '\\':
- array[l++] = '\\';
+ c = '\\';
break;
case '0': case '1': case '2': case '3':
case '4': case '5': case '6': case '7':
@@ -590,7 +599,7 @@ rl_translate_keyseq (const char *seq, char *array, int *len)
for (temp = 2, c -= '0'; ISOCTAL ((unsigned char)seq[i]) && temp--; i++)
c = (c * 8) + OCTVALUE (seq[i]);
i--; /* auto-increment in for loop */
- array[l++] = c & largest_char;
+ c &= largest_char;
break;
case 'x':
i++;
@@ -599,16 +608,40 @@ rl_translate_keyseq (const char *seq, char *array, int *len)
if (temp == 2)
c = 'x';
i--; /* auto-increment in for loop */
- array[l++] = c & largest_char;
+ c &= largest_char;
break;
default: /* backslashes before non-special chars just add the char */
- array[l++] = c;
+ c &= largest_char;
break; /* the backslash is stripped */
}
- continue;
}
- array[l++] = c;
+ /* Process \C- and \M- flags */
+ if (has_control)
+ {
+ /* Special treatment for C-? */
+ c = (c == '?') ? RUBOUT : CTRL (_rl_to_upper (c));
+ has_control = 0;
+ }
+ if (has_meta)
+ {
+ c = META (c);
+ has_meta = 0;
+ }
+
+ /* If convert-meta is turned on, convert a meta char to a key sequence */
+ if (META_CHAR (c) && _rl_convert_meta_chars_to_ascii)
+ {
+ array[l++] = ESC; /* ESC is meta-prefix */
+ array[l++] = UNMETA (c);
+ }
+ else
+ array[l++] = (c);
+
+ /* Null characters may be processed for incomplete prefixes at the end of
+ sequence */
+ if (seq[i] == '\0')
+ break;
}
*len = l;
@@ -756,7 +789,7 @@ _rl_untranslate_macro_value (char *seq, int use_escapes)
/* Return a pointer to the function that STRING represents.
If STRING doesn't have a matching function, then a NULL pointer
- is returned. */
+ is returned. The string match is case-insensitive. */
rl_command_func_t *
rl_named_function (const char *string)
{
@@ -809,7 +842,7 @@ _rl_function_of_keyseq_internal (const char *keyseq, size_t len, Keymap map, int
{
/* If this is the last key in the key sequence, return the
map. */
- if (keyseq[i + 1] == '\0')
+ if (i + 1 == len)
{
if (type)
*type = ISKMAP;
@@ -822,9 +855,9 @@ _rl_function_of_keyseq_internal (const char *keyseq, size_t len, Keymap map, int
/* If we're not at the end of the key sequence, and the current key
is bound to something other than a keymap, then the entire key
sequence is not bound. */
- else if (map[ic].type != ISKMAP && keyseq[i+1])
+ else if (map[ic].type != ISKMAP && i+1 < len)
return ((rl_command_func_t *)NULL);
- else /* map[ic].type != ISKMAP && keyseq[i+1] == 0 */
+ else /* map[ic].type != ISKMAP && i+1 == len */
{
if (type)
*type = map[ic].type;
@@ -1569,15 +1602,11 @@ rl_parse_and_bind (char *string)
/* 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';
+ /* just read a whitespace-delimited word or empty string */
+ for (e = value; *e && whitespace (*e) == 0; e++)
+ ;
+ if (e > value)
+ *e = '\0'; /* cut off everything trailing */
}
else if ((i = find_string_var (var)) >= 0)
{
@@ -1589,9 +1618,24 @@ remove_trailing:
value++; /* skip past the quote */
}
else
- goto remove_trailing;
+ {
+ /* remove trailing whitespace */
+ 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
+ {
+ /* avoid calling rl_variable_bind just to find this out */
+ _rl_init_file_error ("%s: unknown variable name", var);
+ return 1;
+ }
+
rl_variable_bind (var, value);
return 0;
}
@@ -1768,7 +1812,7 @@ static const struct {
{ "convert-meta", &_rl_convert_meta_chars_to_ascii, 0 },
{ "disable-completion", &rl_inhibit_completion, 0 },
{ "echo-control-characters", &_rl_echo_control_chars, 0 },
- { "enable-bracketed-paste", &_rl_enable_bracketed_paste, 0 },
+ { "enable-bracketed-paste", &_rl_enable_bracketed_paste, V_SPECIAL },
{ "enable-keypad", &_rl_enable_keypad, 0 },
{ "enable-meta-key", &_rl_enable_meta, 0 },
{ "expand-tilde", &rl_complete_with_tilde_expansion, 0 },
@@ -1834,6 +1878,8 @@ hack_special_boolean_var (int i)
}
else if (_rl_stricmp (name, "show-mode-in-prompt") == 0)
_rl_reset_prompt ();
+ else if (_rl_stricmp (name, "enable-bracketed-paste") == 0)
+ _rl_enable_active_region = _rl_enable_bracketed_paste;
}
typedef int _rl_sv_func_t PARAMS((const char *));
@@ -1903,7 +1949,7 @@ string_varname (int i)
}
/* A boolean value that can appear in a `set variable' command is true if
- the value is null or empty, `on' (case-insensitive), or "1". Any other
+ the value is null or empty, `on' (case-insensitive), or "1". All other
values result in 0 (false). */
static int
bool_to_int (const char *value)
@@ -1928,7 +1974,7 @@ rl_variable_value (const char *name)
return (_rl_get_string_variable_value (string_varlist[i].name));
/* Unknown variable names return NULL. */
- return 0;
+ return (char *)NULL;
}
int
@@ -1959,6 +2005,8 @@ rl_variable_bind (const char *name, const char *value)
}
v = (*string_varlist[i].set_func) (value);
+ if (v != 0)
+ _rl_init_file_error ("%s: could not set value to `%s'", name, value);
return v;
}
@@ -2581,20 +2629,22 @@ rl_invoking_keyseqs_in_map (rl_command_func_t *function, Keymap map)
else
sprintf (keyname, "\\e");
}
- else if (CTRL_CHAR (key))
- sprintf (keyname, "\\C-%c", _rl_to_lower (UNCTRL (key)));
- else if (key == RUBOUT)
- sprintf (keyname, "\\C-?");
- else if (key == '\\' || key == '"')
- {
- keyname[0] = '\\';
- keyname[1] = (char) key;
- keyname[2] = '\0';
- }
else
{
- keyname[0] = (char) key;
- keyname[1] = '\0';
+ int c = key, l = 0;
+ if (CTRL_CHAR (c) || c == RUBOUT)
+ {
+ keyname[l++] = '\\';
+ keyname[l++] = 'C';
+ keyname[l++] = '-';
+ c = (c == RUBOUT) ? '?' : _rl_to_lower (UNCTRL (c));
+ }
+
+ if (c == '\\' || c == '"')
+ keyname[l++] = '\\';
+
+ keyname[l++] = (char) c;
+ keyname[l++] = '\0';
}
strcat (keyname, seqs[i]);
diff --git a/lib/readline/colors.c b/lib/readline/colors.c
index 53758e0e..9e37527e 100644
--- a/lib/readline/colors.c
+++ b/lib/readline/colors.c
@@ -2,7 +2,7 @@
Modified by Chet Ramey for Readline.
- Copyright (C) 1985, 1988, 1990-1991, 1995-2010, 2012, 2015, 2017
+ Copyright (C) 1985, 1988, 1990-1991, 1995-2010, 2012, 2015, 2017, 2019
Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
@@ -32,6 +32,13 @@
#include "rlconf.h"
+#if defined __TANDEM
+# define _XOPEN_SOURCE_EXTENDED 1
+# define _TANDEM_SOURCE 1
+# include <sys/types.h>
+# include <sys/stat.h>
+#endif
+
#include <stdio.h>
#include "posixstat.h" // stat related macros (S_ISREG, ...)
@@ -175,7 +182,7 @@ _rl_print_color_indicator (const char *f)
if (linkok == -1 && _rl_color_indicator[C_MISSING].string != NULL)
colored_filetype = C_MISSING;
- else if (linkok == 0 && S_ISLNK(mode) && _rl_color_indicator[C_ORPHAN].string != NULL)
+ else if (linkok == 0 && _rl_color_indicator[C_ORPHAN].string != NULL)
colored_filetype = C_ORPHAN; /* dangling symlink */
else if(stat_ok != 0)
{
diff --git a/lib/readline/complete.c b/lib/readline/complete.c
index adce0d69..fc5c3adb 100644
--- a/lib/readline/complete.c
+++ b/lib/readline/complete.c
@@ -1,6 +1,6 @@
/* complete.c -- filename completion for readline. */
-/* Copyright (C) 1987-2017 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2020 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.
@@ -21,11 +21,18 @@
#define READLINE_LIBRARY
+#if defined (__TANDEM)
+# define _XOPEN_SOURCE_EXTENDED 1
+#endif
+
#if defined (HAVE_CONFIG_H)
# include <config.h>
#endif
#include <sys/types.h>
+#if defined (__TANDEM)
+# include <sys/stat.h>
+#endif
#include <fcntl.h>
#if defined (HAVE_SYS_FILE_H)
# include <sys/file.h>
@@ -141,6 +148,7 @@ static int complete_fncmp PARAMS((const char *, int, const char *, int));
static void display_matches PARAMS((char **));
static int compute_lcd_of_matches PARAMS((char **, int, const char *));
static int postprocess_matches PARAMS((char ***, int));
+static int compare_match PARAMS((char *, const char *));
static int complete_get_screenwidth PARAMS((void));
static char *make_quoted_replacement PARAMS((char *, int, char *));
@@ -406,6 +414,7 @@ int rl_sort_completion_matches = 1;
/* Local variable states what happened during the last completion attempt. */
static int completion_changed_buffer;
+static int last_completion_failed = 0;
/* The result of the query to the user about displaying completion matches */
static int completion_y_or_n;
@@ -428,7 +437,11 @@ rl_complete (int ignore, int invoking_key)
if (rl_inhibit_completion)
return (_rl_insert_char (ignore, invoking_key));
- else if (rl_last_func == rl_complete && !completion_changed_buffer)
+#if 0
+ else if (rl_last_func == rl_complete && completion_changed_buffer == 0 && last_completion_failed == 0)
+#else
+ else if (rl_last_func == rl_complete && completion_changed_buffer == 0)
+#endif
return (rl_complete_internal ('?'));
else if (_rl_complete_show_all)
return (rl_complete_internal ('!'));
@@ -477,7 +490,7 @@ rl_completion_mode (rl_command_func_t *cfunc)
/* */
/************************************/
-/* Reset readline state on a signal or other event. */
+/* Reset public readline state on a signal or other event. */
void
_rl_reset_completion_state (void)
{
@@ -1330,12 +1343,13 @@ compute_lcd_of_matches (char **match_list, int matches, const char *text)
memset (&ps2, 0, sizeof (mbstate_t));
}
#endif
- if (_rl_completion_case_fold)
+ for (si = 0; (c1 = match_list[i][si]) && (c2 = match_list[i + 1][si]); si++)
{
- for (si = 0;
- (c1 = _rl_to_lower(match_list[i][si])) &&
- (c2 = _rl_to_lower(match_list[i + 1][si]));
- si++)
+ if (_rl_completion_case_fold)
+ {
+ c1 = _rl_to_lower (c1);
+ c2 = _rl_to_lower (c2);
+ }
#if defined (HANDLE_MULTIBYTE)
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
{
@@ -1347,8 +1361,11 @@ compute_lcd_of_matches (char **match_list, int matches, const char *text)
break;
continue;
}
- wc1 = towlower (wc1);
- wc2 = towlower (wc2);
+ if (_rl_completion_case_fold)
+ {
+ wc1 = towlower (wc1);
+ wc2 = towlower (wc2);
+ }
if (wc1 != wc2)
break;
else if (v1 > 1)
@@ -1359,27 +1376,6 @@ compute_lcd_of_matches (char **match_list, int matches, const char *text)
if (c1 != c2)
break;
}
- else
- {
- for (si = 0;
- (c1 = match_list[i][si]) &&
- (c2 = match_list[i + 1][si]);
- si++)
-#if defined (HANDLE_MULTIBYTE)
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- {
- mbstate_t ps_back;
- ps_back = ps1;
- if (!_rl_compare_chars (match_list[i], si, &ps1, match_list[i+1], si, &ps2))
- break;
- else if ((v = _rl_get_char_len (&match_list[i][si], &ps_back)) > 1)
- si += v - 1;
- }
- else
-#endif
- if (c1 != c2)
- break;
- }
if (low > si)
low = si;
@@ -1969,6 +1965,26 @@ _rl_free_match_list (char **matches)
xfree (matches);
}
+/* Compare a possibly-quoted filename TEXT from the line buffer and a possible
+ MATCH that is the product of filename completion, which acts on the dequoted
+ text. */
+static int
+compare_match (char *text, const char *match)
+{
+ char *temp;
+ int r;
+
+ if (rl_filename_completion_desired && rl_filename_quoting_desired &&
+ rl_completion_found_quote && rl_filename_dequoting_function)
+ {
+ temp = (*rl_filename_dequoting_function) (text, rl_completion_quote_character);
+ r = strcmp (temp, match);
+ free (temp);
+ return r;
+ }
+ return (strcmp (text, match));
+}
+
/* Complete the word at or before point.
WHAT_TO_DO says what to do with the completion.
`?' means list the possible completions.
@@ -1986,10 +2002,12 @@ rl_complete_internal (int what_to_do)
int start, end, delimiter, found_quote, i, nontrivial_lcd;
char *text, *saved_line_buffer;
char quote_char;
- int tlen, mlen;
+ int tlen, mlen, saved_last_completion_failed;
RL_SETSTATE(RL_STATE_COMPLETING);
+ saved_last_completion_failed = last_completion_failed;
+
set_completion_defaults (what_to_do);
saved_line_buffer = rl_line_buffer ? savestring (rl_line_buffer) : (char *)NULL;
@@ -2013,7 +2031,7 @@ rl_complete_internal (int what_to_do)
matches = gen_completion_matches (text, start, end, our_func, found_quote, quote_char);
/* nontrivial_lcd is set if the common prefix adds something to the word
being completed. */
- nontrivial_lcd = matches && strcmp (text, matches[0]) != 0;
+ nontrivial_lcd = matches && compare_match (text, matches[0]) != 0;
if (what_to_do == '!' || what_to_do == '@')
tlen = strlen (text);
xfree (text);
@@ -2023,6 +2041,7 @@ rl_complete_internal (int what_to_do)
rl_ding ();
FREE (saved_line_buffer);
completion_changed_buffer = 0;
+ last_completion_failed = 1;
RL_UNSETSTATE(RL_STATE_COMPLETING);
_rl_reset_completion_state ();
return (0);
@@ -2038,11 +2057,15 @@ rl_complete_internal (int what_to_do)
rl_ding ();
FREE (saved_line_buffer);
completion_changed_buffer = 0;
+ last_completion_failed = 1;
RL_UNSETSTATE(RL_STATE_COMPLETING);
_rl_reset_completion_state ();
return (0);
}
+ if (matches && matches[0] && *matches[0])
+ last_completion_failed = 0;
+
switch (what_to_do)
{
case TAB:
@@ -2098,6 +2121,15 @@ rl_complete_internal (int what_to_do)
break;
case '?':
+ /* Let's try to insert a single match here if the last completion failed
+ but this attempt returned a single match. */
+ if (saved_last_completion_failed && matches[0] && *matches[0] && matches[1] == 0)
+ {
+ insert_match (matches[0], start, matches[1] ? MULT_MATCH : SINGLE_MATCH, &quote_char);
+ append_to_match (matches[0], delimiter, quote_char, nontrivial_lcd);
+ break;
+ }
+
if (rl_completion_display_matches_hook == 0)
{
_rl_sigcleanup = _rl_complete_sigcleanup;
@@ -2761,7 +2793,7 @@ rl_old_menu_complete (int count, int invoking_key)
{
insert_match (matches[match_list_index], orig_start, SINGLE_MATCH, &quote_char);
append_to_match (matches[match_list_index], delimiter, quote_char,
- strcmp (orig_text, matches[match_list_index]));
+ compare_match (orig_text, matches[match_list_index]));
}
completion_changed_buffer = 1;
@@ -2835,7 +2867,7 @@ rl_menu_complete (int count, int ignore)
matches = gen_completion_matches (orig_text, orig_start, orig_end,
our_func, found_quote, quote_char);
- nontrivial_lcd = matches && strcmp (orig_text, matches[0]) != 0;
+ nontrivial_lcd = matches && compare_match (orig_text, matches[0]) != 0;
/* If we are matching filenames, the attempted completion function will
have set rl_filename_completion_desired to a non-zero value. The basic
@@ -2942,7 +2974,7 @@ rl_menu_complete (int count, int ignore)
{
insert_match (matches[match_list_index], orig_start, SINGLE_MATCH, &quote_char);
append_to_match (matches[match_list_index], delimiter, quote_char,
- strcmp (orig_text, matches[match_list_index]));
+ compare_match (orig_text, matches[match_list_index]));
}
completion_changed_buffer = 1;
diff --git a/lib/readline/display.c b/lib/readline/display.c
index 4c6cc00e..38b3d0e7 100644
--- a/lib/readline/display.c
+++ b/lib/readline/display.c
@@ -1,6 +1,6 @@
/* display.c -- readline redisplay facility. */
-/* Copyright (C) 1987-2017 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2020 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.
@@ -63,23 +63,31 @@
extern char *strchr (), *strrchr ();
#endif /* !strchr && !__STDC__ */
-static void update_line PARAMS((char *, char *, int, int, int, int));
+static void putc_face PARAMS((int, int, char *));
+static void puts_face PARAMS((const char *, const char *, int));
+static void norm_face PARAMS((char *, int));
+
+static void update_line PARAMS((char *, char *, 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));
static void redraw_prompt PARAMS((char *));
+static void _rl_move_cursor_relative PARAMS((int, const char *, const char *));
/* Values for FLAGS */
#define PMT_MULTILINE 0x01
static char *expand_prompt PARAMS((char *, int, int *, int *, int *, int *));
+#define DEFAULT_LINE_BUFFER_SIZE 1024
+
/* State of visible and invisible lines. */
struct line_state
{
char *line;
+ char *lface;
int *lbreaks;
int lbsize;
#if defined (HANDLE_MULTIBYTE)
@@ -102,7 +110,9 @@ static int line_structures_initialized = 0;
#define vis_lbsize (line_state_visible->lbsize)
#define visible_line (line_state_visible->line)
+#define vis_face (line_state_visible->lface)
#define invisible_line (line_state_invisible->line)
+#define inv_face (line_state_invisible->lface)
#if defined (HANDLE_MULTIBYTE)
static int _rl_col_width PARAMS((const char *, int, int, int));
@@ -123,6 +133,10 @@ static int _rl_col_width PARAMS((const char *, int, int, int));
to use prompt_last_invisible directly. */
#define PROMPT_ENDING_INDEX \
((MB_CUR_MAX > 1 && rl_byte_oriented == 0) ? prompt_physical_chars : prompt_last_invisible+1)
+
+#define FACE_NORMAL '0'
+#define FACE_STANDOUT '1'
+#define FACE_INVALID ((char)1)
/* **************************************************************** */
/* */
@@ -190,6 +204,8 @@ int _rl_last_v_pos = 0;
on screen minus 1. */
int _rl_vis_botlin = 0;
+static int _rl_quick_redisplay = 0;
+
/* This is a hint update_line gives to rl_redisplay that it has adjusted the
value of _rl_last_c_pos *and* taken the presence of any invisible chars in
the prompt into account. rl_redisplay notes this and does not do the
@@ -219,7 +235,11 @@ static int msg_bufsiz = 0;
static int forced_display;
/* Default and initial buffer size. Can grow. */
-static int line_size = 1024;
+static int line_size = 0;
+
+/* Set to a non-zero value if horizontal scrolling has been enabled
+ automatically because the terminal was resized to height 1. */
+static int horizontal_scrolling_autoset = 0; /* explicit initialization */
/* Variables to keep track of the expanded prompt string, which may
include invisible characters. */
@@ -574,11 +594,6 @@ rl_expand_prompt (char *prompt)
{
/* The prompt spans multiple lines. */
t = ++p;
- local_prompt = expand_prompt (p, PMT_MULTILINE,
- &prompt_visible_length,
- &prompt_last_invisible,
- &prompt_invis_chars_first_line,
- &prompt_physical_chars);
c = *t; *t = '\0';
/* The portion of the prompt string up to and including the
final newline is now null-terminated. */
@@ -588,11 +603,53 @@ rl_expand_prompt (char *prompt)
(int *)NULL,
(int *)NULL);
*t = c;
+
+ local_prompt = expand_prompt (p, PMT_MULTILINE,
+ &prompt_visible_length,
+ &prompt_last_invisible,
+ &prompt_invis_chars_first_line,
+ &prompt_physical_chars);
local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
return (prompt_prefix_length);
}
}
+/* Allocate the various line structures, making sure they can hold MINSIZE
+ bytes. If the existing line size can accommodate MINSIZE bytes, don't do
+ anything. */
+static void
+realloc_line (int minsize)
+{
+ int minimum_size;
+ int newsize, delta;
+
+ minimum_size = DEFAULT_LINE_BUFFER_SIZE;
+ if (minsize < minimum_size)
+ minsize = minimum_size;
+ if (minsize <= _rl_screenwidth) /* XXX - for gdb */
+ minsize = _rl_screenwidth + 1;
+ if (line_size >= minsize)
+ return;
+
+ newsize = minimum_size;
+ while (newsize < minsize)
+ newsize *= 2;
+
+ visible_line = (char *)xrealloc (visible_line, newsize);
+ vis_face = (char *)xrealloc (vis_face, newsize);
+
+ invisible_line = (char *)xrealloc (invisible_line, newsize);
+ inv_face = (char *)xrealloc (inv_face, newsize);
+
+ delta = newsize - line_size;
+ memset (visible_line + line_size, 0, delta);
+ memset (vis_face + line_size, FACE_NORMAL, delta);
+ memset (invisible_line + line_size, 1, delta);
+ memset (inv_face + line_size, FACE_INVALID, delta);
+
+ line_size = newsize;
+}
+
/* Initialize the VISIBLE_LINE and INVISIBLE_LINE arrays, and their associated
arrays of line break markers. MINSIZE is the minimum size of VISIBLE_LINE
and INVISIBLE_LINE; if it is greater than LINE_SIZE, LINE_SIZE is
@@ -601,29 +658,12 @@ rl_expand_prompt (char *prompt)
static void
init_line_structures (int minsize)
{
- register int n;
-
if (invisible_line == 0) /* initialize it */
{
- if (line_size < minsize)
- line_size = minsize;
- visible_line = (char *)xmalloc (line_size);
- invisible_line = (char *)xmalloc (line_size);
- }
- else if (line_size < minsize) /* ensure it can hold MINSIZE chars */
- {
- line_size *= 2;
- if (line_size < minsize)
- line_size = minsize;
- visible_line = (char *)xrealloc (visible_line, line_size);
- invisible_line = (char *)xrealloc (invisible_line, line_size);
- }
-
- for (n = minsize; n < line_size; n++)
- {
- visible_line[n] = 0;
- invisible_line[n] = 1;
+ if (line_size > minsize)
+ minsize = line_size;
}
+ realloc_line (minsize);
if (vis_lbreaks == 0)
{
@@ -645,16 +685,68 @@ init_line_structures (int minsize)
line_structures_initialized = 1;
}
-
+
+/* Convenience functions to add chars to the invisible line that update the
+ face information at the same time. */
+static void /* XXX - change this */
+invis_addc (int *outp, char c, char face)
+{
+ realloc_line (*outp + 1);
+ invisible_line[*outp] = c;
+ inv_face[*outp] = face;
+ *outp += 1;
+}
+
+static void
+invis_adds (int *outp, const char *str, int n, char face)
+{
+ int i;
+
+ for (i = 0; i < n; i++)
+ invis_addc (outp, str[i], face);
+}
+
+static void
+invis_nul (int *outp)
+{
+ invis_addc (outp, '\0', 0);
+ *outp -= 1;
+}
+
+static void
+set_active_region (int *beg, int *end)
+{
+ if (rl_point >= 0 && rl_point <= rl_end && rl_mark >= 0 && rl_mark <= rl_end)
+ {
+ *beg = (rl_mark < rl_point) ? rl_mark : rl_point;
+ *end = (rl_mark < rl_point) ? rl_point : rl_mark;
+ }
+}
+
+/* Do whatever tests are necessary and tell update_line that it can do a
+ quick, dumb redisplay on the assumption that there are so many
+ differences between the old and new lines that it would be a waste to
+ compute all the differences.
+ Right now, it just sets _rl_quick_redisplay if the current visible line
+ is a single line (so we don't have to move vertically or mess with line
+ wrapping). */
+void
+_rl_optimize_redisplay (void)
+{
+ if (_rl_vis_botlin == 0)
+ _rl_quick_redisplay = 1;
+}
+
/* Basic redisplay algorithm. See comments inline. */
void
rl_redisplay (void)
{
- register int in, out, c, linenum, cursor_linenum;
- register char *line;
+ int in, out, c, linenum, cursor_linenum;
int inv_botlin, lb_botlin, lb_linenum, o_cpos;
int newlines, lpos, temp, n0, num, prompt_lines_estimate;
char *prompt_this_line;
+ char cur_face;
+ int hl_begin, hl_end;
int mb_cur_max = MB_CUR_MAX;
#if defined (HANDLE_MULTIBYTE)
wchar_t wc;
@@ -672,6 +764,14 @@ rl_redisplay (void)
_rl_block_sigint ();
RL_SETSTATE (RL_STATE_REDISPLAYING);
+ cur_face = FACE_NORMAL;
+ /* Can turn this into an array for multiple highlighted objects in addition
+ to the region */
+ hl_begin = hl_end = -1;
+
+ if (rl_mark_active_p ())
+ set_active_region (&hl_begin, &hl_end);
+
if (!rl_display_prompt)
rl_display_prompt = "";
@@ -680,13 +780,26 @@ rl_redisplay (void)
init_line_structures (0);
rl_on_new_line ();
}
+ else if (line_size <= _rl_screenwidth)
+ init_line_structures (_rl_screenwidth + 1);
+
+ /* Enable horizontal scrolling automatically for terminals of height 1
+ where wrapping lines doesn't work. Disable it as soon as the terminal
+ height is increased again if it was automatically enabled. */
+ if (_rl_screenheight <= 1)
+ {
+ if (_rl_horizontal_scroll_mode == 0)
+ horizontal_scrolling_autoset = 1;
+ _rl_horizontal_scroll_mode = 1;
+ }
+ else if (horizontal_scrolling_autoset)
+ _rl_horizontal_scroll_mode = 0;
/* Draw the line into the buffer. */
cpos_buffer_position = -1;
prompt_multibyte_chars = prompt_visible_length - prompt_physical_chars;
- line = invisible_line;
out = inv_botlin = 0;
/* Mark the line as modified or not. We only do this for history
@@ -694,8 +807,8 @@ rl_redisplay (void)
modmark = 0;
if (_rl_mark_modified_lines && current_history () && rl_undo_list)
{
- line[out++] = '*';
- line[out] = '\0';
+ invis_addc (&out, '*', cur_face);
+ invis_nul (&out);
modmark = 1;
}
@@ -708,7 +821,7 @@ rl_redisplay (void)
/* If the prompt to be displayed is the `primary' readline prompt (the
one passed to readline()), use the values we have already expanded.
If not, use what's already in rl_display_prompt. WRAP_OFFSET is the
- number of non-visible characters in the prompt string. */
+ number of non-visible characters (bytes) in the prompt string. */
/* This is where we output the characters in the prompt before the last
newline, if any. If there aren't any embedded newlines, we don't
write anything. Copy the last line of the prompt string into the line in
@@ -719,18 +832,8 @@ rl_redisplay (void)
_rl_output_some_chars (local_prompt_prefix, strlen (local_prompt_prefix));
if (local_prompt_len > 0)
- {
- temp = local_prompt_len + out + 2;
- if (temp >= line_size)
- {
- line_size = (temp + 1024) - (temp % 1024);
- visible_line = (char *)xrealloc (visible_line, line_size);
- line = invisible_line = (char *)xrealloc (invisible_line, line_size);
- }
- strncpy (line + out, local_prompt, local_prompt_len);
- out += local_prompt_len;
- }
- line[out] = '\0';
+ invis_adds (&out, local_prompt, local_prompt_len, cur_face);
+ invis_nul (&out);
wrap_offset = local_prompt_len - prompt_visible_length;
}
else
@@ -753,17 +856,9 @@ rl_redisplay (void)
}
}
- prompt_physical_chars = pmtlen = strlen (prompt_this_line);
- temp = pmtlen + out + 2;
- if (temp >= line_size)
- {
- line_size = (temp + 1024) - (temp % 1024);
- visible_line = (char *)xrealloc (visible_line, line_size);
- line = invisible_line = (char *)xrealloc (invisible_line, line_size);
- }
- strncpy (line + out, prompt_this_line, pmtlen);
- out += pmtlen;
- line[out] = '\0';
+ prompt_physical_chars = pmtlen = strlen (prompt_this_line); /* XXX */
+ invis_adds (&out, prompt_this_line, pmtlen, cur_face);
+ invis_nul (&out);
wrap_offset = prompt_invis_chars_first_line = 0;
}
@@ -844,8 +939,8 @@ rl_redisplay (void)
num = 0;
#endif
- /* prompt_invis_chars_first_line is the number of invisible characters in
- the first physical line of the prompt.
+ /* prompt_invis_chars_first_line is the number of invisible characters (bytes)
+ in the first physical line of the prompt.
wrap_offset - prompt_invis_chars_first_line is usually the number of
invis chars on the second (or, more generally, last) line. */
@@ -901,6 +996,11 @@ rl_redisplay (void)
for (in = 0; in < rl_end; in++)
#endif
{
+ if (in == hl_begin)
+ cur_face = FACE_STANDOUT;
+ else if (in == hl_end)
+ cur_face = FACE_NORMAL;
+
c = (unsigned char)rl_line_buffer[in];
#if defined (HANDLE_MULTIBYTE)
@@ -925,14 +1025,6 @@ rl_redisplay (void)
}
#endif
- if (out + 8 >= line_size) /* XXX - 8 for \t */
- {
- line_size *= 2;
- visible_line = (char *)xrealloc (visible_line, line_size);
- invisible_line = (char *)xrealloc (invisible_line, line_size);
- line = invisible_line;
- }
-
if (in == rl_point)
{
cpos_buffer_position = out;
@@ -947,9 +1039,12 @@ rl_redisplay (void)
{
if (_rl_output_meta_chars == 0)
{
- sprintf (line + out, "\\%o", c);
+ char obuf[5];
+ int olen;
- if (lpos + 4 >= _rl_screenwidth)
+ olen = sprintf (obuf, "\\%o", c);
+
+ if (lpos + olen >= _rl_screenwidth)
{
temp = _rl_screenwidth - lpos;
CHECK_INV_LBREAKS ();
@@ -957,16 +1052,20 @@ rl_redisplay (void)
#if defined (HANDLE_MULTIBYTE)
line_state_invisible->wrapped_line[newlines] = _rl_wrapped_multicolumn;
#endif
- lpos = 4 - temp;
+ lpos = olen - temp;
}
else
- lpos += 4;
+ lpos += olen;
- out += 4;
+ for (temp = 0; temp < olen; temp++)
+ {
+ invis_addc (&out, obuf[temp], cur_face);
+ CHECK_LPOS ();
+ }
}
else
{
- line[out++] = c;
+ invis_addc (&out, c, cur_face);
CHECK_LPOS();
}
}
@@ -975,11 +1074,7 @@ rl_redisplay (void)
{
register int newout;
-#if 0
- newout = (out | (int)7) + 1;
-#else
newout = out + 8 - lpos % 8;
-#endif
temp = newout - out;
if (lpos + temp >= _rl_screenwidth)
{
@@ -992,19 +1087,19 @@ rl_redisplay (void)
#endif
lpos = temp - temp2;
while (out < newout)
- line[out++] = ' ';
+ invis_addc (&out, ' ', cur_face);
}
else
{
while (out < newout)
- line[out++] = ' ';
+ invis_addc (&out, ' ', cur_face);
lpos += temp;
}
}
#endif
else if (c == '\n' && _rl_horizontal_scroll_mode == 0 && _rl_term_up && *_rl_term_up)
{
- line[out++] = '\0'; /* XXX - sentinel */
+ invis_addc (&out, '\0', cur_face);
CHECK_INV_LBREAKS ();
inv_lbreaks[++newlines] = out;
#if defined (HANDLE_MULTIBYTE)
@@ -1014,9 +1109,9 @@ rl_redisplay (void)
}
else if (CTRL_CHAR (c) || c == RUBOUT)
{
- line[out++] = '^';
+ invis_addc (&out, '^', cur_face);
CHECK_LPOS();
- line[out++] = CTRL_CHAR (c) ? UNCTRL (c) : '?';
+ invis_addc (&out, CTRL_CHAR (c) ? UNCTRL (c) : '?', cur_face);
CHECK_LPOS();
}
else
@@ -1032,7 +1127,7 @@ rl_redisplay (void)
for (i = lpos; i < _rl_screenwidth; i++)
{
/* The space will be removed in update_line() */
- line[out++] = ' ';
+ invis_addc (&out, ' ', cur_face);
_rl_wrapped_multicolumn++;
CHECK_LPOS();
}
@@ -1042,17 +1137,17 @@ rl_redisplay (void)
lb_linenum = newlines;
}
for (i = in; i < in+wc_bytes; i++)
- line[out++] = rl_line_buffer[i];
+ invis_addc (&out, rl_line_buffer[i], cur_face);
for (i = 0; i < wc_width; i++)
CHECK_LPOS();
}
else
{
- line[out++] = c;
+ invis_addc (&out, c, cur_face);
CHECK_LPOS();
}
#else
- line[out++] = c;
+ invis_addc (&out, c, cur_face);
CHECK_LPOS();
#endif
}
@@ -1074,7 +1169,7 @@ rl_redisplay (void)
in++;
#endif
}
- line[out] = '\0';
+ invis_nul (&out);
line_totbytes = out;
if (cpos_buffer_position < 0)
{
@@ -1082,6 +1177,11 @@ rl_redisplay (void)
lb_linenum = newlines;
}
+ /* If we are switching from one line to multiple wrapped lines, we don't
+ want to do a dumb update (or we want to make it smarter). */
+ if (_rl_quick_redisplay && newlines > 0)
+ _rl_quick_redisplay = 0;
+
inv_botlin = lb_botlin = _rl_inv_botlin = newlines;
CHECK_INV_LBREAKS ();
inv_lbreaks[newlines+1] = out;
@@ -1118,7 +1218,7 @@ rl_redisplay (void)
{
#if defined (HANDLE_MULTIBYTE)
if (mb_cur_max > 1 && rl_byte_oriented == 0)
- out = _rl_find_prev_mbchar (line, _rl_screenchars, MB_FIND_ANY);
+ out = _rl_find_prev_mbchar (invisible_line, _rl_screenchars, MB_FIND_ANY);
else
#endif
out = _rl_screenchars - 1;
@@ -1136,14 +1236,32 @@ rl_redisplay (void)
#define VIS_LLEN(l) ((l) > _rl_vis_botlin ? 0 : (vis_lbreaks[l+1] - vis_lbreaks[l]))
#define INV_LLEN(l) (inv_lbreaks[l+1] - inv_lbreaks[l])
#define VIS_CHARS(line) (visible_line + vis_lbreaks[line])
+#define VIS_FACE(line) (vis_face + vis_lbreaks[line])
#define VIS_LINE(line) ((line) > _rl_vis_botlin) ? "" : VIS_CHARS(line)
+#define VIS_LINE_FACE(line) ((line) > _rl_vis_botlin) ? "" : VIS_FACE(line)
#define INV_LINE(line) (invisible_line + inv_lbreaks[line])
+#define INV_LINE_FACE(line) (inv_face + inv_lbreaks[line])
#define OLD_CPOS_IN_PROMPT() (cpos_adjusted == 0 && \
_rl_last_c_pos != o_cpos && \
_rl_last_c_pos > wrap_offset && \
o_cpos < prompt_last_invisible)
+
+ /* We don't want to highlight anything that's going to be off the top
+ of the display; if the current line takes up more than an entire
+ screen, just mark the lines that won't be displayed as having a
+ `normal' face.
+ It's imperfect, but better than display corruption. */
+ if (rl_mark_active_p () && inv_botlin > _rl_screenheight)
+ {
+ int extra;
+
+ extra = inv_botlin - _rl_screenheight;
+ for (linenum = 0; linenum <= extra; linenum++)
+ norm_face (INV_LINE_FACE(linenum), INV_LLEN (linenum));
+ }
+
/* For each line in the buffer, do the updating display. */
for (linenum = 0; linenum <= inv_botlin; linenum++)
{
@@ -1151,7 +1269,9 @@ rl_redisplay (void)
the locale from a non-multibyte to a multibyte one. */
o_cpos = _rl_last_c_pos;
cpos_adjusted = 0;
- update_line (VIS_LINE(linenum), INV_LINE(linenum), linenum,
+ update_line (VIS_LINE(linenum), VIS_LINE_FACE(linenum),
+ INV_LINE(linenum), INV_LINE_FACE(linenum),
+ linenum,
VIS_LLEN(linenum), INV_LLEN(linenum), inv_botlin);
/* update_line potentially changes _rl_last_c_pos, but doesn't
@@ -1199,19 +1319,35 @@ rl_redisplay (void)
_rl_clear_to_eol (nleft);
}
#if 0
- /* This segment is intended to handle the case where the prompt
- has invisible characters on the second line and the new line
+ /* This segment is intended to handle the case where the old
+ visible prompt has invisible characters and the new line
to be displayed needs to clear the rest of the old characters
- out (e.g., when printing the i-search prompt). In general,
- the case of the new line being shorter than the old.
- Incomplete */
- else if (linenum == prompt_last_screen_line &&
- prompt_physical_chars > _rl_screenwidth &&
- wrap_offset != prompt_invis_chars_first_line &&
+ out (e.g., when printing the i-search prompt): in general,
+ the case of the new line being shorter than the old. We need
+ to be at the end of the new line and the old line needs to be
+ longer than the current cursor position. It's not perfect,
+ since it uses the byte length of the first line, but this will
+ at worst result in some extra clear-to-end-of-lines. We can't
+ use the prompt length variables because they may not
+ correspond to the visible line (see printing the i-search
+ prompt above). The tests for differing numbers of invisible
+ characters may not matter and can probably be removed. */
+ else if (linenum == 0 &&
+ linenum == prompt_last_screen_line &&
_rl_last_c_pos == out &&
+ _rl_last_c_pos < visible_first_line_len &&
+ visible_wrap_offset &&
+ visible_wrap_offset != wrap_offset)
+ {
+ if (mb_cur_max > 1 && rl_byte_oriented == 0)
+ nleft = _rl_screenwidth - _rl_last_c_pos;
+ else
+ nleft = _rl_screenwidth + wrap_offset - _rl_last_c_pos;
+ if (nleft)
+ _rl_clear_to_eol (nleft);
+ }
#endif
-
/* Since the new first line is now visible, save its length. */
if (linenum == 0)
visible_first_line_len = (inv_botlin > 0) ? inv_lbreaks[1] : out - wrap_offset;
@@ -1226,7 +1362,7 @@ rl_redisplay (void)
{
tt = VIS_CHARS (linenum);
_rl_move_vert (linenum);
- _rl_move_cursor_relative (0, tt);
+ _rl_move_cursor_relative (0, tt, VIS_FACE(linenum));
_rl_clear_to_eol
((linenum == _rl_vis_botlin) ? strlen (tt) : _rl_screenwidth);
}
@@ -1255,20 +1391,12 @@ rl_redisplay (void)
the characters from the current cursor position. But we
only need to reprint it if the cursor is before the last
invisible character in the prompt string. */
+ /* XXX - why not use local_prompt_len? */
nleft = prompt_visible_length + wrap_offset;
if (cursor_linenum == 0 && wrap_offset > 0 && _rl_last_c_pos > 0 &&
-#if 0
- _rl_last_c_pos <= PROMPT_ENDING_INDEX && local_prompt)
-#else
_rl_last_c_pos < PROMPT_ENDING_INDEX && local_prompt)
-#endif
{
-#if defined (__MSDOS__)
- putc ('\r', rl_outstream);
-#else
- if (_rl_term_cr)
- tputs (_rl_term_cr, 1, _rl_output_character_function);
-#endif
+ _rl_cr ();
if (modmark)
_rl_output_some_chars ("*", 1);
@@ -1282,8 +1410,8 @@ rl_redisplay (void)
/* Where on that line? And where does that line start
in the buffer? */
pos = inv_lbreaks[cursor_linenum];
- /* nleft == number of characters in the line buffer between the
- start of the line and the desired cursor position. */
+ /* nleft == number of characters (bytes) in the line buffer between
+ the start of the line and the desired cursor position. */
nleft = cpos_buffer_position - pos;
/* NLEFT is now a number of characters in a buffer. When in a
@@ -1314,9 +1442,9 @@ rl_redisplay (void)
point specified by a buffer position (NLEFT) that doesn't take
invisible characters into account. */
if (mb_cur_max > 1 && rl_byte_oriented == 0)
- _rl_move_cursor_relative (nleft, &invisible_line[pos]);
+ _rl_move_cursor_relative (nleft, &invisible_line[pos], &inv_face[pos]);
else if (nleft != _rl_last_c_pos)
- _rl_move_cursor_relative (nleft, &invisible_line[pos]);
+ _rl_move_cursor_relative (nleft, &invisible_line[pos], &inv_face[pos]);
}
}
else /* Do horizontal scrolling. Much simpler */
@@ -1372,7 +1500,7 @@ rl_redisplay (void)
/* 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)
- line[lmargin] = '<';
+ invisible_line[lmargin] = '<';
/* If SCREENWIDTH characters starting at LMARGIN do not encompass
the whole line, indicate that with a special character at the
@@ -1380,15 +1508,15 @@ rl_redisplay (void)
wrap offset into account. */
t = lmargin + M_OFFSET (lmargin, wrap_offset) + _rl_screenwidth;
if (t > 0 && t < out)
- line[t - 1] = '>';
+ invisible_line[t - 1] = '>';
if (rl_display_fixed == 0 || forced_display || lmargin != last_lmargin)
{
forced_display = 0;
o_cpos = _rl_last_c_pos;
cpos_adjusted = 0;
- update_line (&visible_line[last_lmargin],
- &invisible_line[lmargin],
+ update_line (&visible_line[last_lmargin], &vis_face[last_lmargin],
+ &invisible_line[lmargin], &inv_face[lmargin],
0,
_rl_screenwidth + visible_wrap_offset,
_rl_screenwidth + (lmargin ? 0 : wrap_offset),
@@ -1413,7 +1541,7 @@ rl_redisplay (void)
if (visible_first_line_len > _rl_screenwidth)
visible_first_line_len = _rl_screenwidth;
- _rl_move_cursor_relative (cpos_buffer_position - lmargin, &invisible_line[lmargin]);
+ _rl_move_cursor_relative (cpos_buffer_position - lmargin, &invisible_line[lmargin], &inv_face[lmargin]);
last_lmargin = lmargin;
}
}
@@ -1434,22 +1562,64 @@ rl_redisplay (void)
visible_wrap_offset = 0;
else
visible_wrap_offset = wrap_offset;
+
+ _rl_quick_redisplay = 0;
}
RL_UNSETSTATE (RL_STATE_REDISPLAYING);
_rl_release_sigint ();
}
+static void
+putc_face (int c, int face, char *cur_face)
+{
+ char cf;
+ cf = *cur_face;
+ if (cf != face)
+ {
+ if (cf != FACE_NORMAL && cf != FACE_STANDOUT)
+ return;
+ if (face != FACE_NORMAL && face != FACE_STANDOUT)
+ return;
+ if (face == FACE_STANDOUT && cf == FACE_NORMAL)
+ _rl_standout_on ();
+ if (face == FACE_NORMAL && cf == FACE_STANDOUT)
+ _rl_standout_off ();
+ *cur_face = face;
+ }
+ if (c != EOF)
+ putc (c, rl_outstream);
+}
+
+static void
+puts_face (const char *str, const char *face, int n)
+{
+ int i;
+ char cur_face;
+
+ for (cur_face = FACE_NORMAL, i = 0; i < n; i++)
+ putc_face (str[i], face[i], &cur_face);
+ putc_face (EOF, FACE_NORMAL, &cur_face);
+}
+
+static void
+norm_face (char *face, int n)
+{
+ memset (face, FACE_NORMAL, n);
+}
+
+#define ADJUST_CPOS(x) do { _rl_last_c_pos -= (x) ; cpos_adjusted = 1; } while (0)
+
/* PWP: update_line() is based on finding the middle difference of each
line on the screen; vis:
/old first difference
- /beginning of line | /old last same /old EOL
- v v v v
+ /beginning of line | /old last same /old EOL
+ v v v v
old: eddie> Oh, my little gruntle-buggy is to me, as lurgid as
new: eddie> Oh, my little buggy says to me, as lurgid as
- ^ ^ ^ ^
- \beginning of line | \new last same \new end of line
+ ^ ^ ^ ^
+ \beginning of line | \new last same \new end of line
\new first difference
All are character pointers for the sake of speed. Special cases for
@@ -1457,9 +1627,10 @@ new: eddie> Oh, my little buggy says to me, as lurgid as
Could be made even smarter, but this works well enough */
static void
-update_line (char *old, char *new, int current_line, int omax, int nmax, int inv_botlin)
+update_line (char *old, char *old_face, char *new, char *new_face, int current_line, int omax, int nmax, int inv_botlin)
{
- register char *ofd, *ols, *oe, *nfd, *nls, *ne;
+ char *ofd, *ols, *oe, *nfd, *nls, *ne;
+ char *ofdf, *nfdf, *olsf, *nlsf;
int temp, lendiff, wsatend, od, nd, twidth, o_cpos;
int current_invis_chars;
int col_lendiff, col_temp;
@@ -1594,17 +1765,24 @@ update_line (char *old, char *new, int current_line, int omax, int nmax, int inv
int count, i, j;
char *optr;
- _rl_output_some_chars (new, newbytes);
+ puts_face (new, new_face, newbytes);
_rl_last_c_pos = newwidth;
_rl_last_v_pos++;
/* 5a. If the number of screen positions doesn't match, punt
- and do a dumb update. */
- if (newwidth != oldwidth)
+ and do a dumb update.
+ 5b. If the number of bytes is greater in the new line than
+ the old, do a dumb update, because there is no guarantee we
+ can extend the old line enough to fit the new bytes. */
+ if (newwidth != oldwidth || newbytes > oldbytes)
{
+ oe = old + omax;
ne = new + nmax;
nd = newbytes;
nfd = new + nd;
+ ofdf = old_face + oldbytes;
+ nfdf = new_face + newbytes;
+
goto dumb_update;
}
if (oldbytes != 0 && newbytes != 0)
@@ -1613,13 +1791,21 @@ update_line (char *old, char *new, int current_line, int omax, int nmax, int inv
consume the first character of old. Fix up `old' so it
reflects the new screen contents. We use +1 in the
memmove call to copy the trailing NUL. */
- memmove (old+newbytes, old+oldbytes, strlen (old+oldbytes) + 1);
+ /* (strlen(old+oldbytes) == (omax - oldbytes - 1)) */
+
+ /* Don't bother trying to fit the bytes if the number of bytes
+ doesn't change. */
+ if (oldbytes != newbytes)
+ {
+ memmove (old+newbytes, old+oldbytes, strlen (old+oldbytes) + 1);
+ memmove (old_face+newbytes, old_face+oldbytes, strlen (old+oldbytes) + 1);
+ }
memcpy (old, new, newbytes);
+ memcpy (old_face, new_face, newbytes);
j = newbytes - oldbytes;
-
omax += j;
/* Fix up indices if we copy data from one line to another */
- for (i = current_line+1; i <= inv_botlin+1; i++)
+ for (i = current_line+1; j != 0 && i <= inv_botlin+1 && i <=_rl_vis_botlin+1; i++)
vis_lbreaks[i] += j;
}
}
@@ -1629,23 +1815,71 @@ update_line (char *old, char *new, int current_line, int omax, int nmax, int inv
_rl_last_c_pos = 1;
_rl_last_v_pos++;
if (old[0] && new[0])
- old[0] = new[0];
+ {
+ old[0] = new[0];
+ old_face[0] = new_face[0];
+ }
}
}
else
#endif
{
if (new[0])
- putc (new[0], rl_outstream);
+ puts_face (new, new_face, 1);
else
putc (' ', rl_outstream);
_rl_last_c_pos = 1;
_rl_last_v_pos++;
if (old[0] && new[0])
- old[0] = new[0];
+ {
+ old[0] = new[0];
+ old_face[0] = new_face[0];
+ }
}
}
+ /* We know that we are dealing with a single screen line here */
+ if (_rl_quick_redisplay)
+ {
+ nfd = new;
+ nfdf = new_face;
+ ofd = old;
+ ofdf = old_face;
+ for (od = 0, oe = ofd; od < omax && *oe; oe++, od++);
+ for (nd = 0, ne = nfd; nd < nmax && *ne; ne++, nd++);
+ od = nd = 0;
+ _rl_move_cursor_relative (0, old, old_face);
+
+ bytes_to_insert = ne - nfd;
+ if (bytes_to_insert < local_prompt_len) /* ??? */
+ goto dumb_update;
+
+ /* output the prompt, output the line contents, clear the rest */
+ _rl_output_some_chars (nfd, local_prompt_len);
+ if (mb_cur_max > 1 && rl_byte_oriented == 0)
+ _rl_last_c_pos = prompt_physical_chars;
+ else
+ _rl_last_c_pos = local_prompt_len;
+
+ bytes_to_insert -= local_prompt_len;
+ if (bytes_to_insert > 0)
+ {
+ puts_face (new+local_prompt_len, nfdf+local_prompt_len, bytes_to_insert);
+ if (mb_cur_max > 1 && rl_byte_oriented)
+ _rl_last_c_pos += _rl_col_width (new, local_prompt_len, ne-new, 1);
+ else
+ _rl_last_c_pos += bytes_to_insert;
+ }
+
+ /* See comments at dumb_update: for an explanation of this heuristic */
+ if (nmax < omax)
+ goto clear_rest_of_line;
+ else if ((nmax - W_OFFSET(current_line, wrap_offset)) < (omax - W_OFFSET (current_line, visible_wrap_offset)))
+ goto clear_rest_of_line;
+ else
+ return;
+ }
+
/* Find first difference. */
#if defined (HANDLE_MULTIBYTE)
if (mb_cur_max > 1 && rl_byte_oriented == 0)
@@ -1653,11 +1887,13 @@ update_line (char *old, char *new, int current_line, int omax, int nmax, int inv
/* See if the old line is a subset of the new line, so that the
only change is adding characters. */
temp = (omax < nmax) ? omax : nmax;
- if (memcmp (old, new, temp) == 0) /* adding at the end */
+ if (memcmp (old, new, temp) == 0 && memcmp (old_face, new_face, temp) == 0)
{
- new_offset = old_offset = temp;
+ new_offset = old_offset = temp; /* adding at the end */
ofd = old + temp;
+ ofdf = old_face + temp;
nfd = new + temp;
+ nfdf = new_face + temp;
}
else
{
@@ -1665,36 +1901,42 @@ update_line (char *old, char *new, int current_line, int omax, int nmax, int inv
memset (&ps_old, 0, sizeof(mbstate_t));
/* Are the old and new lines the same? */
- if (omax == nmax && STREQN (new, old, omax))
+ if (omax == nmax && memcmp (new, old, omax) == 0 && memcmp (new_face, old_face, omax) == 0)
{
old_offset = omax;
new_offset = nmax;
ofd = old + omax;
+ ofdf = old_face + omax;
nfd = new + nmax;
+ nfdf = new_face + nmax;
}
else
{
/* Go through the line from the beginning and find the first
- difference. */
+ difference. We assume that faces change at (possibly multi-
+ byte) character boundaries. */
new_offset = old_offset = 0;
- for (ofd = old, nfd = new;
+ for (ofd = old, ofdf = old_face, nfd = new, nfdf = new_face;
(ofd - old < omax) && *ofd &&
- _rl_compare_chars(old, old_offset, &ps_old, new, new_offset, &ps_new); )
+ _rl_compare_chars(old, old_offset, &ps_old, new, new_offset, &ps_new) &&
+ *ofdf == *nfdf; )
{
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;
+ ofdf = old_face + old_offset;
nfd = new + new_offset;
+ nfdf = new_face + new_offset;
}
}
}
}
else
#endif
- for (ofd = old, nfd = new;
- (ofd - old < omax) && *ofd && (*ofd == *nfd);
- ofd++, nfd++)
+ for (ofd = old, ofdf = old_face, nfd = new, nfdf = new_face;
+ (ofd - old < omax) && *ofd && (*ofd == *nfd) && (*ofdf == *nfdf);
+ ofd++, nfd++, ofdf++, nfdf++)
;
/* Move to the end of the screen line. ND and OD are used to keep track
@@ -1723,7 +1965,9 @@ update_line (char *old, char *new, int current_line, int omax, int nmax, int inv
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 */
+ ofdf = old_face + old_offset;
nfd = new + new_offset;
+ nfdf = new_face + new_offset;
}
}
#endif
@@ -1736,40 +1980,41 @@ update_line (char *old, char *new, int current_line, int omax, int nmax, int inv
if (mb_cur_max > 1 && rl_byte_oriented == 0)
{
ols = old + _rl_find_prev_mbchar (old, oe - old, MB_FIND_ANY);
+ olsf = old_face + (ols - old);
nls = new + _rl_find_prev_mbchar (new, ne - new, MB_FIND_ANY);
+ nlsf = new_face + (nls - new);
while ((ols > ofd) && (nls > nfd))
{
memset (&ps_old, 0, sizeof (mbstate_t));
memset (&ps_new, 0, sizeof (mbstate_t));
-#if 0
- /* On advice from jir@yamato.ibm.com */
- _rl_adjust_point (old, ols - old, &ps_old);
- _rl_adjust_point (new, nls - new, &ps_new);
-#endif
-
- if (_rl_compare_chars (old, ols - old, &ps_old, new, nls - new, &ps_new) == 0)
+ if (_rl_compare_chars (old, ols - old, &ps_old, new, nls - new, &ps_new) == 0 ||
+ *olsf != *nlsf)
break;
if (*ols == ' ')
wsatend = 0;
ols = old + _rl_find_prev_mbchar (old, ols - old, MB_FIND_ANY);
+ olsf = old_face + (ols - old);
nls = new + _rl_find_prev_mbchar (new, nls - new, MB_FIND_ANY);
+ nlsf = new_face + (nls - new);
}
}
else
{
#endif /* HANDLE_MULTIBYTE */
ols = oe - 1; /* find last same */
+ olsf = old_face + (ols - old);
nls = ne - 1;
- while ((ols > ofd) && (nls > nfd) && (*ols == *nls))
+ nlsf = new_face + (nls - new);
+ while ((ols > ofd) && (nls > nfd) && (*ols == *nls) && (*olsf == *nlsf))
{
if (*ols != ' ')
wsatend = 0;
- ols--;
- nls--;
+ ols--; olsf--;
+ nls--; nlsf--;
}
#if defined (HANDLE_MULTIBYTE)
}
@@ -1778,15 +2023,17 @@ update_line (char *old, char *new, int current_line, int omax, int nmax, int inv
if (wsatend)
{
ols = oe;
+ olsf = old_face + (ols - old);
nls = ne;
+ nlsf = new_face + (nls - new);
}
#if defined (HANDLE_MULTIBYTE)
/* This may not work for stateful encoding, but who cares? To handle
stateful encoding properly, we have to scan each string from the
beginning and compare. */
- else if (_rl_compare_chars (ols, 0, NULL, nls, 0, NULL) == 0)
+ else if (_rl_compare_chars (ols, 0, NULL, nls, 0, NULL) == 0 || *olsf != *nlsf)
#else
- else if (*ols != *nls)
+ else if (*ols != *nls || *olsf != *nlsf)
#endif
{
if (*ols) /* don't step past the NUL */
@@ -1803,6 +2050,8 @@ update_line (char *old, char *new, int current_line, int omax, int nmax, int inv
else
nls++;
}
+ olsf = old_face + (ols - old);
+ nlsf = new_face + (nls - new);
}
/* count of invisible characters in the current invisible line. */
@@ -1815,6 +2064,10 @@ update_line (char *old, char *new, int current_line, int omax, int nmax, int inv
visible_wrap_offset based on what we know. */
if (current_line == 0)
visible_wrap_offset = prompt_invis_chars_first_line; /* XXX */
+#if 0 /* XXX - not yet */
+ else if (current_line == prompt_last_screen_line && wrap_offset > prompt_invis_chars_first_line)
+ visible_wrap_offset = wrap_offset - prompt_invis_chars_first_line
+#endif
if ((mb_cur_max == 1 || rl_byte_oriented) && current_line == 0 && visible_wrap_offset)
_rl_last_c_pos += visible_wrap_offset;
}
@@ -1852,19 +2105,21 @@ update_line (char *old, char *new, int current_line, int omax, int nmax, int inv
(((od > 0 || nd > 0) && (od <= prompt_last_invisible || nd <= prompt_last_invisible)) ||
((od >= lendiff) && _rl_last_c_pos < PROMPT_ENDING_INDEX)))
{
-#if defined (__MSDOS__)
- putc ('\r', rl_outstream);
-#else
- tputs (_rl_term_cr, 1, _rl_output_character_function);
-#endif
+ _rl_cr ();
if (modmark)
_rl_output_some_chars ("*", 1);
_rl_output_some_chars (local_prompt, lendiff);
if (mb_cur_max > 1 && rl_byte_oriented == 0)
{
- /* We take wrap_offset into account here so we can pass correct
- information to _rl_move_cursor_relative. */
- _rl_last_c_pos = _rl_col_width (local_prompt, 0, lendiff, 1) - wrap_offset + modmark;
+ /* If we just output the entire prompt string we can take advantage
+ of knowing the number of physical characters in the prompt. If
+ the prompt wraps lines (lendiff clamped at nmax), we can't. */
+ if (lendiff == local_prompt_len)
+ _rl_last_c_pos = prompt_physical_chars + modmark;
+ else
+ /* We take wrap_offset into account here so we can pass correct
+ information to _rl_move_cursor_relative. */
+ _rl_last_c_pos = _rl_col_width (local_prompt, 0, lendiff, 1) - wrap_offset + modmark;
cpos_adjusted = 1;
}
else
@@ -1885,10 +2140,11 @@ update_line (char *old, char *new, int current_line, int omax, int nmax, int inv
to just output the prompt from the beginning of the line up to the
first difference, but you don't know the number of invisible
characters in that case.
- This needs a lot of work to be efficient. */
+ This needs a lot of work to be efficient, but it usually doesn't matter. */
if ((od <= prompt_last_invisible || nd <= prompt_last_invisible))
{
nfd = new + lendiff; /* number of characters we output above */
+ nfdf = new_face + lendiff;
nd = lendiff;
/* Do a dumb update and return */
@@ -1896,7 +2152,7 @@ dumb_update:
temp = ne - nfd;
if (temp > 0)
{
- _rl_output_some_chars (nfd, temp);
+ puts_face (nfd, nfdf, temp);
if (mb_cur_max > 1 && rl_byte_oriented == 0)
{
_rl_last_c_pos += _rl_col_width (new, nd, ne - new, 1);
@@ -1910,16 +2166,33 @@ dumb_update:
current_line == prompt_last_screen_line &&
prompt_physical_chars > _rl_screenwidth &&
_rl_horizontal_scroll_mode == 0)
- {
- _rl_last_c_pos -= wrap_offset - prompt_invis_chars_first_line;
- cpos_adjusted = 1;
- }
+ ADJUST_CPOS (wrap_offset - prompt_invis_chars_first_line);
+
+ /* If we just output a new line including the prompt, and
+ the prompt includes invisible characters, we need to
+ account for them in the _rl_last_c_pos calculation, since
+ _rl_col_width does not. This happens when other code does
+ a goto dumb_update; */
+ else if (current_line == 0 &&
+ nfd == new &&
+ prompt_invis_chars_first_line &&
+ local_prompt_len <= temp &&
+ wrap_offset >= prompt_invis_chars_first_line &&
+ _rl_horizontal_scroll_mode == 0)
+ ADJUST_CPOS (prompt_invis_chars_first_line);
}
else
_rl_last_c_pos += temp;
}
+ /* This is a useful heuristic, but what we really want is to clear
+ if the new number of visible screen characters is less than the
+ old number of visible screen characters. If the prompt has changed,
+ we don't really have enough information about the visible line to
+ know for sure, so we use another heuristic calclulation below. */
if (nmax < omax)
goto clear_rest_of_line; /* XXX */
+ else if ((nmax - W_OFFSET(current_line, wrap_offset)) < (omax - W_OFFSET (current_line, visible_wrap_offset)))
+ goto clear_rest_of_line;
else
return;
}
@@ -1930,7 +2203,7 @@ dumb_update:
/* When this function returns, _rl_last_c_pos is correct, and an absolute
cursor position in multibyte mode, but a buffer index when not in a
multibyte locale. */
- _rl_move_cursor_relative (od, old);
+ _rl_move_cursor_relative (od, old, old_face);
#if defined (HANDLE_MULTIBYTE)
/* We need to indicate that the cursor position is correct in the presence of
@@ -1948,15 +2221,76 @@ dumb_update:
When not using multibyte characters, these are equal */
lendiff = (nls - nfd) - (ols - ofd);
if (mb_cur_max > 1 && rl_byte_oriented == 0)
- col_lendiff = _rl_col_width (new, nfd - new, nls - new, 1) - _rl_col_width (old, ofd - old, ols - old, 1);
+ {
+ int newchars, newwidth, newind;
+ int oldchars, oldwidth, oldind;
+
+ newchars = nls - new;
+ oldchars = ols - old;
+
+ /* If we can do it, try to adjust nls and ols so that nls-new will
+ contain the entire new prompt string. That way we can use
+ prompt_physical_chars and not have to recompute column widths.
+ _rl_col_width adds wrap_offset and expects the caller to compensate,
+ which we do below, so we do the same thing if we don't call
+ _rl_col_width.
+ We don't have to compare, since we know the characters are the same.
+ The check of differing numbers of invisible chars may be extraneous.
+ XXX - experimental */
+ if (current_line == 0 && nfd == new && newchars > prompt_last_invisible &&
+ newchars <= local_prompt_len &&
+ local_prompt_len <= nmax &&
+ current_invis_chars != visible_wrap_offset)
+ {
+ while (newchars < nmax && oldchars < omax && newchars < local_prompt_len)
+ {
+#if defined (HANDLE_MULTIBYTE)
+ newind = _rl_find_next_mbchar (new, newchars, 1, MB_FIND_NONZERO);
+ oldind = _rl_find_next_mbchar (old, oldchars, 1, MB_FIND_NONZERO);
+
+ nls += newind - newchars;
+ ols += oldind - oldchars;
+
+ newchars = newind;
+ oldchars = oldind;
+#else
+ nls++; ols++;
+ newchars++; oldchars++;
+#endif
+ }
+ newwidth = (newchars == local_prompt_len) ? prompt_physical_chars + wrap_offset
+ : _rl_col_width (new, 0, nls - new, 1);
+ /* if we changed nls and ols, we need to recompute lendiff */
+ lendiff = (nls - nfd) - (ols - ofd);
+
+ nlsf = new_face + (nls - new);
+ olsf = old_face + (ols - old);
+ }
+ else
+ newwidth = _rl_col_width (new, nfd - new, nls - new, 1);
+
+ oldwidth = _rl_col_width (old, ofd - old, ols - old, 1);
+
+ col_lendiff = newwidth - oldwidth;
+ }
else
col_lendiff = lendiff;
+ /* col_lendiff uses _rl_col_width(), which doesn't know about whether or not
+ the multibyte characters it counts are invisible, so unless we're printing
+ the entire prompt string (in which case we can use prompt_physical_chars)
+ the count is short by the number of bytes in the invisible multibyte
+ characters - the number of multibyte characters.
+
+ We don't have a good way to solve this without moving to something like
+ a bitmap that indicates which characters are visible and which are
+ invisible. We fix it up (imperfectly) in the caller and by trying to use
+ the entire prompt string wherever we can. */
+
/* If we are changing the number of invisible characters in a line, and
the spot of first difference is before the end of the invisible chars,
lendiff needs to be adjusted. */
- if (current_line == 0 && /* !_rl_horizontal_scroll_mode && */
- current_invis_chars != visible_wrap_offset)
+ if (current_line == 0 && current_invis_chars != visible_wrap_offset)
{
if (mb_cur_max > 1 && rl_byte_oriented == 0)
{
@@ -1998,16 +2332,13 @@ dumb_update:
only happen in a multibyte environment. */
if (lendiff < 0)
{
- _rl_output_some_chars (nfd, temp);
- _rl_last_c_pos += col_temp; /* XXX - was _rl_col_width (nfd, 0, temp, 1); */
+ puts_face (nfd, nfdf, temp);
+ _rl_last_c_pos += col_temp;
/* 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 && displaying_prompt_first_line && wrap_offset && ((nfd - new) <= prompt_last_invisible))
- {
- _rl_last_c_pos -= wrap_offset; /* XXX - prompt_invis_chars_first_line? */
- cpos_adjusted = 1;
- }
+ ADJUST_CPOS (wrap_offset); /* XXX - prompt_invis_chars_first_line? */
return;
}
/* Sometimes it is cheaper to print the characters rather than
@@ -2035,7 +2366,7 @@ dumb_update:
(visible_wrap_offset >= current_invis_chars))
{
open_some_spaces (col_lendiff);
- _rl_output_some_chars (nfd, bytes_to_insert);
+ puts_face (nfd, nfdf, 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
@@ -2045,22 +2376,19 @@ dumb_update:
{
/* At the end of a line the characters do not have to
be "inserted". They can just be placed on the screen. */
- _rl_output_some_chars (nfd, temp);
+ puts_face (nfd, nfdf, temp);
_rl_last_c_pos += col_temp;
return;
}
else /* just write from first difference to end of new line */
{
- _rl_output_some_chars (nfd, temp);
+ puts_face (nfd, nfdf, 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 && displaying_prompt_first_line && wrap_offset && ((nfd - new) <= prompt_last_invisible))
- {
- _rl_last_c_pos -= wrap_offset; /* XXX - prompt_invis_chars_first_line? */
- cpos_adjusted = 1;
- }
+ ADJUST_CPOS (wrap_offset); /* XXX - prompt_invis_chars_first_line? */
return;
}
@@ -2070,16 +2398,13 @@ dumb_update:
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 && displaying_prompt_first_line && wrap_offset && ((nfd - new) <= prompt_last_invisible))
- {
- _rl_last_c_pos -= wrap_offset; /* XXX - prompt_invis_chars_first_line? */
- cpos_adjusted = 1;
- }
+ ADJUST_CPOS (wrap_offset); /* XXX - prompt_invis_chars_first_line? */
}
}
else
{
/* cannot insert chars, write to EOL */
- _rl_output_some_chars (nfd, temp);
+ puts_face (nfd, nfdf, temp);
_rl_last_c_pos += col_temp;
/* If we're in a multibyte locale and were before the last invisible
char in the current line (which implies we just output some invisible
@@ -2094,10 +2419,11 @@ dumb_update:
displaying_prompt_first_line &&
wrap_offset != prompt_invis_chars_first_line &&
((nfd-new) < (prompt_last_invisible-(current_line*_rl_screenwidth+prompt_invis_chars_first_line))))
- {
- _rl_last_c_pos -= wrap_offset - prompt_invis_chars_first_line;
- cpos_adjusted = 1;
- }
+ ADJUST_CPOS (wrap_offset - prompt_invis_chars_first_line);
+
+ /* XXX - what happens if wrap_offset == prompt_invis_chars_first_line
+ and we are drawing the first line (current_line == 0)? We should
+ adjust by _rl_last_c_pos -= prompt_invis_chars_first_line */
}
}
else /* Delete characters from line. */
@@ -2132,18 +2458,18 @@ dumb_update:
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, bytes_to_insert);
+ puts_face (nfd, nfdf, bytes_to_insert);
if (mb_cur_max > 1 && rl_byte_oriented == 0)
{
+ /* This still doesn't take into account whether or not the
+ characters that this counts are 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 && /* XXX was > */
+ prompt_invis_chars_first_line &&
+ _rl_last_c_pos >= prompt_invis_chars_first_line &&
((nfd - new) <= prompt_last_invisible))
- {
- _rl_last_c_pos -= wrap_offset; /* XXX - prompt_invis_chars_first_line? */
- cpos_adjusted = 1;
- }
+ ADJUST_CPOS (prompt_invis_chars_first_line);
#if 1
#ifdef HANDLE_MULTIBYTE
@@ -2166,7 +2492,7 @@ dumb_update:
so we move there with _rl_move_cursor_relative */
if (_rl_horizontal_scroll_mode && ((oe-old) > (ne-new)))
{
- _rl_move_cursor_relative (ne-new, new);
+ _rl_move_cursor_relative (ne-new, new, new_face);
goto clear_rest_of_line;
}
}
@@ -2180,7 +2506,7 @@ dumb_update:
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);
+ puts_face (nfd, nfdf, temp);
_rl_last_c_pos += col_temp; /* XXX */
if (mb_cur_max > 1 && rl_byte_oriented == 0)
{
@@ -2188,10 +2514,7 @@ dumb_update:
displaying_prompt_first_line &&
_rl_last_c_pos > wrap_offset &&
((nfd - new) <= prompt_last_invisible))
- {
- _rl_last_c_pos -= wrap_offset; /* XXX - prompt_invis_chars_first_line? */
- cpos_adjusted = 1;
- }
+ ADJUST_CPOS (wrap_offset); /* XXX - prompt_invis_chars_first_line? */
}
}
clear_rest_of_line:
@@ -2240,11 +2563,7 @@ rl_clear_visible_line (void)
int curr_line;
/* Make sure we move to column 0 so we clear the entire line */
-#if defined (__MSDOS__)
- putc ('\r', rl_outstream);
-#else
- tputs (_rl_term_cr, 1, _rl_output_character_function);
-#endif
+ _rl_cr ();
_rl_last_c_pos = 0;
/* Move to the last screen line of the current visible line */
@@ -2357,8 +2676,8 @@ rl_redraw_prompt_last_line (void)
DATA is the contents of the screen line of interest; i.e., where
the movement is being done.
DATA is always the visible line or the invisible line */
-void
-_rl_move_cursor_relative (int new, const char *data)
+static void
+_rl_move_cursor_relative (int new, const char *data, const char *dataf)
{
register int i;
int woff; /* number of invisible chars on current line */
@@ -2455,11 +2774,7 @@ _rl_move_cursor_relative (int new, const char *data)
if (dpos == 0 || CR_FASTER (dpos, _rl_last_c_pos) ||
(_rl_term_autowrap && i == _rl_screenwidth))
{
-#if defined (__MSDOS__)
- putc ('\r', rl_outstream);
-#else
- tputs (_rl_term_cr, 1, _rl_output_character_function);
-#endif /* !__MSDOS__ */
+ _rl_cr ();
cpos = _rl_last_c_pos = 0;
}
@@ -2491,14 +2806,12 @@ _rl_move_cursor_relative (int new, const char *data)
}
else
{
- tputs (_rl_term_cr, 1, _rl_output_character_function);
- for (i = 0; i < new; i++)
- putc (data[i], rl_outstream);
+ _rl_cr ();
+ puts_face (data, dataf, new);
}
}
else
- for (i = cpos; i < new; i++)
- putc (data[i], rl_outstream);
+ puts_face (data + cpos, dataf + cpos, new - cpos);
}
#if defined (HANDLE_MULTIBYTE)
@@ -2526,11 +2839,7 @@ _rl_move_vert (int to)
{
for (i = 0; i < delta; i++)
putc ('\n', rl_outstream);
-#if defined (__MSDOS__)
- putc ('\r', rl_outstream);
-#else
- tputs (_rl_term_cr, 1, _rl_output_character_function);
-#endif
+ _rl_cr ();
_rl_last_c_pos = 0;
}
else
@@ -2871,14 +3180,18 @@ space_to_eol (int count)
}
void
-_rl_clear_screen (void)
+_rl_clear_screen (int clrscr)
{
#if defined (__DJGPP__)
ScreenClear ();
ScreenSetCursor (0, 0);
#else
if (_rl_term_clrpag)
- tputs (_rl_term_clrpag, 1, _rl_output_character_function);
+ {
+ tputs (_rl_term_clrpag, 1, _rl_output_character_function);
+ if (clrscr && _rl_term_clrscroll)
+ tputs (_rl_term_clrscroll, 1, _rl_output_character_function);
+ }
else
rl_crlf ();
#endif /* __DJGPP__ */
@@ -2958,6 +3271,9 @@ _rl_update_final (void)
{
int full_lines, woff, botline_length;
+ if (line_structures_initialized == 0)
+ return;
+
full_lines = 0;
/* If the cursor is the only thing on an otherwise-blank last line,
compensate so we don't print an extra CRLF. */
@@ -2973,7 +3289,7 @@ _rl_update_final (void)
/* If we've wrapped lines, remove the final xterm line-wrap flag. */
if (full_lines && _rl_term_autowrap && botline_length == _rl_screenwidth)
{
- char *last_line;
+ char *last_line, *last_face;
/* LAST_LINE includes invisible characters, so if you want to get the
last character of the first line, you have to take WOFF into account.
@@ -2981,10 +3297,12 @@ _rl_update_final (void)
which takes a buffer position as the first argument, and any direct
subscripts of LAST_LINE. */
last_line = &visible_line[vis_lbreaks[_rl_vis_botlin]]; /* = VIS_CHARS(_rl_vis_botlin); */
+ last_face = &vis_face[vis_lbreaks[_rl_vis_botlin]]; /* = VIS_CHARS(_rl_vis_botlin); */
cpos_buffer_position = -1; /* don't know where we are in buffer */
- _rl_move_cursor_relative (_rl_screenwidth - 1 + woff, last_line); /* XXX */
+ _rl_move_cursor_relative (_rl_screenwidth - 1 + woff, last_line, last_face); /* XXX */
_rl_clear_to_eol (0);
- putc (last_line[_rl_screenwidth - 1 + woff], rl_outstream);
+ puts_face (&last_line[_rl_screenwidth - 1 + woff],
+ &last_face[_rl_screenwidth - 1 + woff], 1);
}
_rl_vis_botlin = 0;
if (botline_length > 0 || _rl_last_c_pos > 0)
@@ -2997,15 +3315,8 @@ _rl_update_final (void)
static void
cr (void)
{
- if (_rl_term_cr)
- {
-#if defined (__MSDOS__)
- putc ('\r', rl_outstream);
-#else
- tputs (_rl_term_cr, 1, _rl_output_character_function);
-#endif
- _rl_last_c_pos = 0;
- }
+ _rl_cr ();
+ _rl_last_c_pos = 0;
}
/* Redraw the last line of a multi-line prompt that may possibly contain
@@ -3048,24 +3359,19 @@ _rl_redisplay_after_sigwinch (void)
{
_rl_move_vert (_rl_vis_botlin);
-#if defined (__MSDOS__)
- putc ('\r', rl_outstream);
-#else
- tputs (_rl_term_cr, 1, _rl_output_character_function);
-#endif
+ _rl_cr ();
_rl_last_c_pos = 0;
-#if defined (__MSDOS__)
- space_to_eol (_rl_screenwidth);
- putc ('\r', rl_outstream);
-#else
+
+#if !defined (__MSDOS__)
if (_rl_term_clreol)
tputs (_rl_term_clreol, 1, _rl_output_character_function);
else
+#endif
{
space_to_eol (_rl_screenwidth);
- tputs (_rl_term_cr, 1, _rl_output_character_function);
+ _rl_cr ();
}
-#endif
+
if (_rl_last_v_pos > 0)
_rl_move_vert (0);
}
@@ -3130,6 +3436,14 @@ _rl_current_display_line (void)
return ret;
}
+void
+_rl_refresh_line (void)
+{
+ rl_clear_visible_line ();
+ rl_redraw_prompt_last_line ();
+ rl_keep_mark_active ();
+}
+
#if defined (HANDLE_MULTIBYTE)
/* Calculate the number of screen columns occupied by STR from START to END.
In the case of multibyte characters with stateful encoding, we have to
diff --git a/lib/readline/doc/history.texi b/lib/readline/doc/history.texi
index 98e22332..7a3a4767 100644
--- a/lib/readline/doc/history.texi
+++ b/lib/readline/doc/history.texi
@@ -12,7 +12,7 @@ This document describes the GNU History library
a programming tool that provides a consistent user interface for
recalling lines of previously typed input.
-Copyright @copyright{} 1988--2016 Free Software Foundation, Inc.
+Copyright @copyright{} 1988--2020 Free Software Foundation, Inc.
@quotation
Permission is granted to copy, distribute and/or modify this document
diff --git a/lib/readline/doc/hstech.texi b/lib/readline/doc/hstech.texi
index dbc21c14..7ac11953 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-2016 Free Software Foundation, Inc.
+Copyright (C) 1988-2020 Free Software Foundation, Inc.
Authored by Brian Fox and Chet Ramey.
Permission is granted to make and distribute verbatim copies of this manual
@@ -48,7 +48,7 @@ History library is able to keep track of those lines, associate arbitrary
data with each line, and utilize information from previous lines in
composing new ones.
-The programmer using the History library has available functions
+A programmer using the History library has available functions
for remembering lines on a history list, associating arbitrary data
with a line, removing lines from the list, searching through the list
for a line containing an arbitrary text string, and referencing any line
@@ -62,7 +62,7 @@ commands for manipulating the text of previous lines and using that text
in new commands. The basic history manipulation commands are similar to
the history substitution provided by @code{csh}.
-If the programmer desires, he can use the Readline library, which
+The programmer can also use the Readline library, which
includes some history manipulation by default, and has the added
advantage of command line editing.
diff --git a/lib/readline/doc/hsuser.texi b/lib/readline/doc/hsuser.texi
index 521ccc70..b8fedf33 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--2018 Free Software Foundation, Inc.
+Copyright (C) 1988--2020 Free Software Foundation, Inc.
Authored by Brian Fox and Chet Ramey.
Permission is granted to make and distribute verbatim copies of this manual
@@ -149,7 +149,14 @@ Both @var{first} and
@var{last} may be specified as a string (to locate the most recent
command beginning with that string) or as a number (an index into the
history list, where a negative number is used as an offset from the
-current command number). If @var{last} is not specified, it is set to
+current command number).
+
+When listing, a @var{first} or @var{last} of 0 is equivalent to -1
+and -0 is equivalent to the current command (usually the @code{fc}
+command);
+otherwise 0 is equivalent to -1 and -0 is invalid.
+
+If @var{last} is not specified, it is set to
@var{first}. If @var{first} is not specified, it is set to the previous
command for editing and @minus{}16 for listing. If the @option{-l} flag is
given, the commands are listed on standard output. The @option{-n} flag
@@ -164,7 +171,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.
+@var{command} is interpreted 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}
@@ -370,11 +377,13 @@ containing @var{string}.
The trailing
@samp{?} may be omitted if the @var{string} is followed immediately by
a newline.
+If @var{string} is missing, the string from the most recent search is used;
+it is an error if there is no previous search string.
@item @code{^@var{string1}^@var{string2}^}
Quick Substitution. Repeat the last command, replacing @var{string1}
with @var{string2}. Equivalent to
-@code{!!:s/@var{string1}/@var{string2}/}.
+@code{!!:s^@var{string1}^@var{string2}^}.
@item @code{!#}
The entire command line typed so far.
@@ -426,7 +435,8 @@ The first argument; that is, word 1.
The last argument.
@item %
-The word matched by the most recent @samp{?@var{string}?} search.
+The first word matched by the most recent @samp{?@var{string}?} search,
+if the search string begins with a character that is part of a word.
@item @var{x}-@var{y}
A range of words; @samp{-@var{y}} abbreviates @samp{0-@var{y}}.
@@ -441,6 +451,7 @@ Abbreviates @samp{@var{x}-$}
@item @var{x}-
Abbreviates @samp{@var{x}-$} like @samp{@var{x}*}, but omits the last word.
+If @samp{x} is missing, it defaults to 0.
@end table
@@ -452,6 +463,7 @@ previous command is used as the event.
After the optional word designator, you can add a sequence of one or more
of the following modifiers, each preceded by a @samp{:}.
+These modify, or edit, the word or words selected from the history event.
@table @code
@@ -478,15 +490,25 @@ Quote the substituted words, escaping further substitutions.
@item x
Quote the substituted words as with @samp{q},
but break into words at spaces, tabs, and newlines.
+The @samp{q} and @samp{x} modifiers are mutually exclusive; the last one
+supplied is used.
@end ifset
@item s/@var{old}/@var{new}/
Substitute @var{new} for the first occurrence of @var{old} in the
-event line. Any delimiter may be used in place of @samp{/}.
+event line.
+Any character may be used as the delimiter in place of @samp{/}.
The delimiter may be quoted in @var{old} and @var{new}
with a single backslash. If @samp{&} appears in @var{new},
it is replaced by @var{old}. A single backslash will quote
-the @samp{&}. The final delimiter is optional if it is the last
+the @samp{&}.
+If @var{old} is null, it is set to the last @var{old}
+substituted, or, if no previous history substitutions took place,
+the last @var{string}
+in a !?@var{string}@code{[?]}
+search.
+If @var{new} is is null, each matching @var{old} is deleted.
+The final delimiter is optional if it is the last
character on the input line.
@item &
@@ -499,6 +521,7 @@ conjunction with @samp{s}, as in @code{gs/@var{old}/@var{new}/},
or with @samp{&}.
@item G
-Apply the following @samp{s} modifier once to each word in the event.
+Apply the following @samp{s} or @samp{&} modifier once to each word
+in the event.
@end table
diff --git a/lib/readline/doc/rlman.texi b/lib/readline/doc/rlman.texi
index 737f971d..ec7487b7 100644
--- a/lib/readline/doc/rlman.texi
+++ b/lib/readline/doc/rlman.texi
@@ -13,7 +13,7 @@ This manual describes the GNU Readline Library
consistency of user interface across discrete programs which provide
a command line interface.
-Copyright @copyright{} 1988--2016 Free Software Foundation, Inc.
+Copyright @copyright{} 1988--2020 Free Software Foundation, Inc.
@quotation
Permission is granted to copy, distribute and/or modify this document
diff --git a/lib/readline/doc/rltech.texi b/lib/readline/doc/rltech.texi
index 28a02d99..bbf57c23 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--2016 Free Software Foundation, Inc.
+Copyright (C) 1988--2020 Free Software Foundation, Inc.
Permission is granted to make and distribute verbatim copies of
this manual provided the copyright notice and this permission notice
@@ -1342,6 +1342,29 @@ This differs from @code{clear_history} because it frees private data
Readline saves in the history list.
@end deftypefun
+@deftypefun {void} rl_activate_mark (void)
+Enable an @emph{active} mark.
+When this is enabled, the text between point and mark (the @var{region}) is
+displayed in the terminal's standout mode (a @var{face}).
+This is called by various readline functions that set the mark and insert
+text, and is available for applications to call.
+@end deftypefun
+
+@deftypefun {void} rl_deactivate_mark (void)
+Turn off the active mark.
+@end deftypefun
+
+@deftypefun {void} rl_keep_mark_active (void)
+Indicate that the mark should remain active when the current readline function
+completes and after redisplay occurs.
+In most cases, the mark remains active for only the duration of a single
+bindable readline function.
+@end deftypefun
+
+@deftypefun {int} rl_mark_active_p (void)
+Return a non-zero value if the mark is currently active; zero otherwise.
+@end deftypefun
+
@node Alternate Interface
@subsection Alternate Interface
@@ -1733,8 +1756,8 @@ to determine whether or not there are any pending signals.
If an application does not wish Readline to catch @code{SIGWINCH}, it may
call @code{rl_resize_terminal()} or @code{rl_set_screen_size()} to force
-Readline to update its idea of the terminal size when a @code{SIGWINCH}
-is received.
+Readline to update its idea of the terminal size when it receives
+a @code{SIGWINCH}.
@deftypefun void rl_echo_signal_char (int sig)
If an application wishes to install its own signal handlers, but still
@@ -1751,11 +1774,14 @@ Update Readline's internal screen size by reading values from the kernel.
Set Readline's idea of the terminal size to @var{rows} rows and
@var{cols} columns. If either @var{rows} or @var{columns} is less than
or equal to 0, Readline's idea of that terminal dimension is unchanged.
+This is intended to tell Readline the physical dimensions of the terminal,
+and is used internally to calculate the maximum number of characters that
+may appear on a single line and on the screen.
@end deftypefun
If an application does not want to install a @code{SIGWINCH} handler, but
-is still interested in the screen dimensions, Readline's idea of the screen
-size may be queried.
+is still interested in the screen dimensions, it may query Readline's idea
+of the screen size.
@deftypefun void rl_get_screen_size (int *rows, int *cols)
Return Readline's idea of the terminal's size in the
@@ -2039,7 +2065,7 @@ remove any quote characters from the directory name, because its result will
be passed directly to @code{opendir()}.
The directory rewrite hook returns an integer that should be non-zero if
-the function modfies its directory argument.
+the function modifies its directory argument.
The function should not modify the directory argument if it returns 0.
@end deftypevar
@@ -2051,7 +2077,7 @@ 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 modifies its directory argument.
The function should not modify the directory argument if it returns 0.
@end deftypevar
@@ -2645,7 +2671,7 @@ com_help (arg)
if (!printed)
@{
- printf ("No commands match `%s'. Possibilties are:\n", arg);
+ printf ("No commands match `%s'. Possibilities are:\n", arg);
for (i = 0; commands[i].name; i++)
@{
diff --git a/lib/readline/doc/rluser.texi b/lib/readline/doc/rluser.texi
index a59bd144..26b0ff07 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--2016 Free Software Foundation, Inc.
+Copyright (C) 1988--2020 Free Software Foundation, Inc.
Authored by Brian Fox and Chet Ramey.
@@ -350,6 +350,11 @@ file is taken from the value of the environment variable @env{INPUTRC}. If
that variable is unset, the default is @file{~/.inputrc}. If that
file does not exist or cannot be read, the ultimate default is
@file{/etc/inputrc}.
+@ifset BashFeatures
+The @w{@code{bind}} builtin command can also be used to set Readline
+keybindings and variables.
+@xref{Bash Builtins}.
+@end ifset
When a program which uses the Readline library starts up, the
init file is read, and the key bindings are set.
@@ -488,9 +493,9 @@ replaced with an ellipsis when displaying possible completions.
@vindex completion-query-items
The number of possible completions that determines when the user is
asked whether the list of possibilities should be displayed.
-If the number of possible completions is greater than this value,
-Readline will ask the user whether or not he wishes to view
-them; otherwise, they are simply listed.
+If the number of possible completions is greater than or equal to this value,
+Readline will ask whether or not the user wishes to view them;
+otherwise, they are simply listed.
This variable must be set to an integer value greater than or equal to 0.
A negative value means Readline should never ask.
The default limit is @code{100}.
@@ -541,7 +546,7 @@ When set to @samp{On}, Readline will configure the terminal in a way
that will enable it to insert each paste into the editing buffer as a
single string of characters, instead of treating each character as if
it had been read from the keyboard. This can prevent pasted characters
-from being interpreted as editing commands. The default is @samp{off}.
+from being interpreted as editing commands. The default is @samp{On}.
@item enable-keypad
@vindex enable-keypad
@@ -583,8 +588,9 @@ the maximum number of history entries will be set to 500.
This variable can be set to either @samp{on} or @samp{off}. Setting it
to @samp{on} means that the text of the lines being edited will scroll
horizontally on a single screen line when they are longer than the width
-of the screen, instead of wrapping onto a new screen line. By default,
-this variable is set to @samp{off}.
+of the screen, instead of wrapping onto a new screen line.
+This variable is automatically set to @samp{on} for terminals of height 1.
+By default, this variable is set to @samp{off}.
@item input-meta
@vindex input-meta
@@ -1109,8 +1115,8 @@ set convert-meta off
# rather than as meta-prefixed characters
set output-meta on
-# if there are more than 150 possible completions for
-# a word, ask the user if he wants to see all of them
+# if there are 150 or more possible completions for a word,
+# ask whether or not the user wants to see all of them
set completion-query-items 150
# For FTP
@@ -1173,11 +1179,11 @@ Move back to the start of the current or previous word.
Words are composed of letters and digits.
@ifset BashFeatures
-@item shell-forward-word ()
+@item shell-forward-word (M-C-f)
Move forward to the end of the next word.
Words are delimited by non-quoted shell metacharacters.
-@item shell-backward-word ()
+@item shell-backward-word (M-C-b)
Move back to the start of the current or previous word.
Words are delimited by non-quoted shell metacharacters.
@end ifset
@@ -1195,8 +1201,14 @@ Readline line does not take up more than one physical line or if the length
of the current Readline line is not greater than the length of the prompt
plus the screen width.
+@item clear-display (M-C-l)
+Clear the screen and, if possible, the terminal's scrollback buffer,
+then redraw the current line,
+leaving the current line at the top of the screen.
+
@item clear-screen (C-l)
-Clear the screen and redraw the current line,
+Clear the screen,
+then redraw the current line,
leaving the current line at the top of the screen.
@item redraw-current-line ()
@@ -1242,10 +1254,12 @@ being entered.
@item reverse-search-history (C-r)
Search backward starting at the current line and moving `up' through
the history as necessary. This is an incremental search.
+This command sets the region to the matched text and activates the mark.
@item forward-search-history (C-s)
Search forward starting at the current line and moving `down' through
the history as necessary. This is an incremental search.
+This command sets the region to the matched text and activates the mark.
@item non-incremental-reverse-search-history (M-p)
Search backward starting at the current line and moving `up'
@@ -1310,6 +1324,14 @@ the direction through the history (back or forward).
The history expansion facilities are used to extract the last argument,
as if the @samp{!$} history expansion had been specified.
+@item operate-and-get-next (C-o)
+Accept the current line for return to the calling application as if a
+newline had been entered,
+and fetch the next line relative to the current line from the history
+for editing.
+A numeric argument, if supplied, specifies the history entry to use instead
+of the current line.
+
@end ftable
@node Commands For Text
@@ -1357,6 +1379,11 @@ each character as if it had been read from the keyboard. The characters
are inserted as if each one was bound to @code{self-insert} instead of
executing any editing commands.
+Bracketed paste sets the region (the characters between point and the mark)
+to the inserted text. It uses the concept of an @emph{active mark}: when the
+mark is active, Readline redisplay uses the terminal's standout mode to
+denote the region.
+
@item transpose-chars (C-t)
Drag the character before the cursor forward over
the character at the cursor, moving the
@@ -1406,9 +1433,13 @@ By default, this command is unbound.
@item kill-line (C-k)
Kill the text from point to the end of the line.
+With a negative numeric argument, kill backward from the cursor to the
+beginning of the current line.
@item backward-kill-line (C-x Rubout)
Kill backward from the cursor to the beginning of the current line.
+With a negative numeric argument, kill forward from the cursor to the
+end of the current line.
@item unix-line-discard (C-u)
Kill backward from the cursor to the beginning of the current line.
@@ -1427,7 +1458,7 @@ Kill the word behind point.
Word boundaries are the same as @code{backward-word}.
@ifset BashFeatures
-@item shell-kill-word ()
+@item shell-kill-word (M-C-d)
Kill from point to the end of the current word, or if between
words, to the end of the next word.
Word boundaries are the same as @code{shell-forward-word}.
@@ -1437,6 +1468,14 @@ Kill the word behind point.
Word boundaries are the same as @code{shell-backward-word}.
@end ifset
+@item shell-transpose-words (M-C-t)
+Drag the word before point past the word after point,
+moving point past that word as well.
+If the insertion point is at the end of the line, this transposes
+the last two words on the line.
+Word boundaries are the same as @code{shell-forward-word} and
+@code{shell-backward-word}.
+
@item unix-word-rubout (C-w)
Kill the word behind point, using white space as a word boundary.
The killed text is saved on the kill-ring.
@@ -1774,12 +1813,6 @@ Perform history and alias expansion on the current line.
@item insert-last-argument (M-. or M-_)
A synonym for @code{yank-last-arg}.
-@item operate-and-get-next (C-o)
-Accept the current line for execution and fetch the next line
-relative to the current line from the history for editing.
-A numeric argument, if supplied, specifies the history entry to use instead
-of the current line.
-
@item edit-and-execute-command (C-x C-e)
Invoke an editor on the current command line, and execute the result as shell
commands.
@@ -2044,7 +2077,7 @@ The @option{-E} option indicates that other supplied options and actions should
apply to ``empty'' command completion; that is, completion attempted on a
blank line.
The @option{-I} option indicates that other supplied options and actions should
-apply to completion on the inital non-assignment word on the line, or after a
+apply to completion on the initial non-assignment word on the line, or after a
command delimiter such as @samp{;} or @samp{|}, which is usually command
name completion.
If multiple options are supplied, the @option{-D} option takes precedence
@@ -2255,7 +2288,7 @@ The @option{-E} option indicates that other supplied options should
apply to ``empty'' command completion; that is, completion attempted on a
blank line.
The @option{-I} option indicates that other supplied options should
-apply to completion on the inital non-assignment word on the line, or after a
+apply to completion on the initial non-assignment word on the line, or after a
command delimiter such as @samp{;} or @samp{|}, which is usually command
name completion.
@@ -2370,7 +2403,7 @@ 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
+for words beginning with @samp{$} or @samp{$@{}, completions containing pathname
expansion patterns (@pxref{Filename Expansion}), and so on.
Once installed using @code{complete}, @code{_comp_cd} will be called every
@@ -2380,7 +2413,7 @@ 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
+at @url{https://github.com/scop/bash-completion/}. 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
diff --git a/lib/readline/doc/rluserman.texi b/lib/readline/doc/rluserman.texi
index b5754389..6e8e848b 100644
--- a/lib/readline/doc/rluserman.texi
+++ b/lib/readline/doc/rluserman.texi
@@ -12,7 +12,7 @@ This manual describes the end user interface of the GNU Readline Library
consistency of user interface across discrete programs which provide
a command line interface.
-Copyright @copyright{} 1988--2016 Free Software Foundation, Inc.
+Copyright @copyright{} 1988--2020 Free Software Foundation, Inc.
@quotation
Permission is granted to copy, distribute and/or modify this document
diff --git a/lib/readline/doc/version.texi b/lib/readline/doc/version.texi
index 576c35c8..abb9cb6b 100644
--- a/lib/readline/doc/version.texi
+++ b/lib/readline/doc/version.texi
@@ -1,10 +1,10 @@
@ignore
-Copyright (C) 1988-2018 Free Software Foundation, Inc.
+Copyright (C) 1988-2020 Free Software Foundation, Inc.
@end ignore
-@set EDITION 8.0
-@set VERSION 8.0
-@set UPDATED 30 November 2018
-@set UPDATED-MONTH November 2018
+@set EDITION 8.1
+@set VERSION 8.1
+@set UPDATED 29 October 2020
+@set UPDATED-MONTH October 2020
-@set LASTCHANGE Fri Nov 30 22:50:53 EST 2018
+@set LASTCHANGE Thu Oct 29 16:49:01 EDT 2020
diff --git a/lib/readline/emacs_keymap.c b/lib/readline/emacs_keymap.c
index b5e53f49..02597dad 100644
--- a/lib/readline/emacs_keymap.c
+++ b/lib/readline/emacs_keymap.c
@@ -47,7 +47,7 @@ KEYMAP_ENTRY_ARRAY emacs_standard_keymap = {
{ ISFUNC, rl_clear_screen }, /* Control-l */
{ ISFUNC, rl_newline }, /* Control-m */
{ ISFUNC, rl_get_next_history }, /* Control-n */
- { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-o */
+ { ISFUNC, rl_operate_and_get_next }, /* Control-o */
{ ISFUNC, rl_get_previous_history }, /* Control-p */
{ ISFUNC, rl_quoted_insert }, /* Control-q */
{ ISFUNC, rl_reverse_search_history }, /* Control-r */
@@ -327,7 +327,7 @@ KEYMAP_ENTRY_ARRAY emacs_meta_keymap = {
{ ISFUNC, rl_tab_insert }, /* Meta-Control-i */
{ ISFUNC, rl_vi_editing_mode }, /* Meta-Control-j */
{ ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-k */
- { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-l */
+ { ISFUNC, rl_clear_display }, /* Meta-Control-l */
{ ISFUNC, rl_vi_editing_mode }, /* Meta-Control-m */
{ ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-n */
{ ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-o */
diff --git a/lib/readline/examples/fileman.c b/lib/readline/examples/fileman.c
index c821df03..2a8b097a 100644
--- a/lib/readline/examples/fileman.c
+++ b/lib/readline/examples/fileman.c
@@ -377,11 +377,11 @@ com_stat (arg)
printf ("Statistics for `%s':\n", arg);
- printf ("%s has %d link%s, and is %d byte%s in length.\n",
+ printf ("%s has %d link%s, and is %lu byte%s in length.\n",
arg,
finfo.st_nlink,
(finfo.st_nlink == 1) ? "" : "s",
- finfo.st_size,
+ (unsigned long)finfo.st_size,
(finfo.st_size == 1) ? "" : "s");
printf ("Inode Last Change at: %s", ctime (&finfo.st_ctime));
printf (" Last access at: %s", ctime (&finfo.st_atime));
@@ -417,7 +417,7 @@ com_help (arg)
if (!printed)
{
- printf ("No commands match `%s'. Possibilties are:\n", arg);
+ printf ("No commands match `%s'. Possibilities are:\n", arg);
for (i = 0; commands[i].name; i++)
{
diff --git a/lib/readline/examples/rltest.c b/lib/readline/examples/rltest.c
index 78e26086..65abe87c 100644
--- a/lib/readline/examples/rltest.c
+++ b/lib/readline/examples/rltest.c
@@ -46,6 +46,7 @@ extern void exit();
extern HIST_ENTRY **history_list ();
+int
main ()
{
char *temp, *prompt;
diff --git a/lib/readline/funmap.c b/lib/readline/funmap.c
index aaf144de..eca49a3e 100644
--- a/lib/readline/funmap.c
+++ b/lib/readline/funmap.c
@@ -1,6 +1,6 @@
/* funmap.c -- attach names to functions. */
-/* Copyright (C) 1987-2017 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2020 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.
@@ -73,6 +73,7 @@ static const FUNMAP default_funmap[] = {
{ "capitalize-word", rl_capitalize_word },
{ "character-search", rl_char_search },
{ "character-search-backward", rl_backward_char_search },
+ { "clear-display", rl_clear_display },
{ "clear-screen", rl_clear_screen },
{ "complete", rl_complete },
{ "copy-backward-word", rl_copy_backward_word },
@@ -116,6 +117,7 @@ static const FUNMAP default_funmap[] = {
{ "non-incremental-forward-search-history-again", rl_noninc_forward_search_again },
{ "non-incremental-reverse-search-history-again", rl_noninc_reverse_search_again },
{ "old-menu-complete", rl_old_menu_complete },
+ { "operate-and-get-next", rl_operate_and_get_next },
{ "overwrite-mode", rl_overwrite_mode },
#if defined (_WIN32)
{ "paste-from-clipboard", rl_paste_from_clipboard },
@@ -157,7 +159,7 @@ static const FUNMAP default_funmap[] = {
{ "vi-backward-bigword", rl_vi_bWord },
{ "vi-backward-word", rl_vi_bword },
{ "vi-bWord", rl_vi_bWord },
- { "vi-bword", rl_vi_bword },
+ { "vi-bword", rl_vi_bword }, /* BEWARE: name matching is case insensitive */
{ "vi-change-case", rl_vi_change_case },
{ "vi-change-char", rl_vi_change_char },
{ "vi-change-to", rl_vi_change_to },
@@ -171,13 +173,13 @@ static const FUNMAP default_funmap[] = {
{ "vi-end-bigword", rl_vi_eWord },
{ "vi-end-word", rl_vi_end_word },
{ "vi-eof-maybe", rl_vi_eof_maybe },
- { "vi-eword", rl_vi_eword },
+ { "vi-eword", rl_vi_eword }, /* BEWARE: name matching is case insensitive */
{ "vi-fWord", rl_vi_fWord },
{ "vi-fetch-history", rl_vi_fetch_history },
{ "vi-first-print", rl_vi_first_print },
{ "vi-forward-bigword", rl_vi_fWord },
{ "vi-forward-word", rl_vi_fword },
- { "vi-fword", rl_vi_fword },
+ { "vi-fword", rl_vi_fword }, /* BEWARE: name matching is case insensitive */
{ "vi-goto-mark", rl_vi_goto_mark },
{ "vi-insert-beg", rl_vi_insert_beg },
{ "vi-insertion-mode", rl_vi_insert_mode },
diff --git a/lib/readline/histexpand.c b/lib/readline/histexpand.c
index adcf5dcb..b986dba0 100644
--- a/lib/readline/histexpand.c
+++ b/lib/readline/histexpand.c
@@ -89,7 +89,7 @@ char history_expansion_char = '!';
char history_subst_char = '^';
/* During tokenization, if this character is seen as the first character
- of a word, then it, and all subsequent characters upto a newline are
+ of a word, then it, and all subsequent characters up to a newline are
ignored. For a Bourne shell, this should be '#'. Bash special cases
the interactive comment character to not be a comment delimiter. */
char history_comment_char = '\0';
@@ -180,7 +180,7 @@ get_history_event (const char *string, int *caller_index, int delimiting_quote)
}
/* Hack case of numeric line specification. */
- if (string[i] == '-')
+ if (string[i] == '-' && _rl_digit_p (string[i+1]))
{
sign = -1;
i++;
@@ -230,10 +230,12 @@ get_history_event (const char *string, int *caller_index, int delimiting_quote)
}
#endif /* HANDLE_MULTIBYTE */
- if ((!substring_okay && (whitespace (c) || c == ':' ||
- (history_event_delimiter_chars && member (c, history_event_delimiter_chars)) ||
- (history_search_delimiter_chars && member (c, history_search_delimiter_chars)) ||
- string[i] == delimiting_quote)) ||
+ if ((!substring_okay &&
+ (whitespace (c) || c == ':' ||
+ (i > local_index && history_event_delimiter_chars && c == '-') ||
+ (c != '-' && history_event_delimiter_chars && member (c, history_event_delimiter_chars)) ||
+ (history_search_delimiter_chars && member (c, history_search_delimiter_chars)) ||
+ string[i] == delimiting_quote)) ||
string[i] == '\n' ||
(substring_okay && string[i] == '?'))
break;
@@ -409,7 +411,10 @@ hist_error(char *s, int start, int current, int errtype)
}
temp = (char *)xmalloc (ll + elen + 3);
- strncpy (temp, s + start, ll);
+ if (s[start])
+ strncpy (temp, s + start, ll);
+ else
+ ll = 0;
temp[ll] = ':';
temp[ll + 1] = ' ';
strcpy (temp + ll + 2, emsg);
@@ -624,7 +629,7 @@ history_expand_internal (char *string, int start, int qc, int *end_index_ptr, ch
return an error state after adding this line to the
history. */
case 'p':
- print_only++;
+ print_only = 1;
break;
/* :t discards all but the last part of the pathname. */
@@ -1356,6 +1361,11 @@ get_history_word_specifier (char *spec, char *from, int *caller_index)
i++;
last = '$';
}
+ else if (spec[i] == '^')
+ {
+ i++;
+ last = 1;
+ }
#if 0
else if (!spec[i] || spec[i] == ':')
/* check against `:' because there could be a modifier separator */
diff --git a/lib/readline/histfile.c b/lib/readline/histfile.c
index 6c3adc9b..f0fa5ce1 100644
--- a/lib/readline/histfile.c
+++ b/lib/readline/histfile.c
@@ -1,6 +1,6 @@
/* histfile.c - functions to manipulate the history file. */
-/* Copyright (C) 1989-2018 Free Software Foundation, Inc.
+/* Copyright (C) 1989-2019 Free Software Foundation, Inc.
This file contains the GNU History Library (History), a set of
routines for managing the text of previously typed lines.
@@ -26,6 +26,8 @@
#define READLINE_LIBRARY
#if defined (__TANDEM)
+# define _XOPEN_SOURCE_EXTENDED 1
+# include <unistd.h>
# include <floss.h>
#endif
@@ -79,6 +81,11 @@
#endif /* HISTORY_USE_MMAP */
+#if defined(_WIN32)
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+#endif
+
/* If we're compiling for __EMX__ (OS/2) or __CYGWIN__ (cygwin32 environment
on win 95/98/nt), we want to open files with O_BINARY mode so that there
is no \n -> \r\n conversion performed. On other systems, we don't want to
@@ -138,6 +145,7 @@ static char *history_backupfile PARAMS((const char *));
static char *history_tempfile PARAMS((const char *));
static int histfile_backup PARAMS((const char *, const char *));
static int histfile_restore PARAMS((const char *, const char *));
+static int history_rename PARAMS((const char *, const char *));
/* Return the string that should be used in the place of this
filename. This only matters when you don't specify the
@@ -449,6 +457,18 @@ read_history_range (const char *filename, int from, int to)
return (0);
}
+/* We need a special version for WIN32 because Windows rename() refuses to
+ overwrite an existing file. */
+static int
+history_rename (const char *old, const char *new)
+{
+#if defined (_WIN32)
+ return (MoveFileEx (old, new, MOVEFILE_REPLACE_EXISTING) == 0 ? -1 : 0);
+#else
+ return (rename (old, new));
+#endif
+}
+
/* Save FILENAME to BACK, handling case where FILENAME is a symlink
(e.g., ~/.bash_history -> .histfiles/.bash_history.$HOSTNAME) */
static int
@@ -462,10 +482,10 @@ histfile_backup (const char *filename, const char *back)
if ((n = readlink (filename, linkbuf, sizeof (linkbuf) - 1)) > 0)
{
linkbuf[n] = '\0';
- return (rename (linkbuf, back));
+ return (history_rename (linkbuf, back));
}
#endif
- return (rename (filename, back));
+ return (history_rename (filename, back));
}
/* Restore ORIG from BACKUP handling case where ORIG is a symlink
@@ -481,12 +501,18 @@ histfile_restore (const char *backup, const char *orig)
if ((n = readlink (orig, linkbuf, sizeof (linkbuf) - 1)) > 0)
{
linkbuf[n] = '\0';
- return (rename (backup, linkbuf));
+ return (history_rename (backup, linkbuf));
}
#endif
- return (rename (backup, orig));
+ return (history_rename (backup, orig));
}
+/* Should we call chown, based on whether finfo and nfinfo describe different
+ files with different owners? */
+
+#define SHOULD_CHOWN(finfo, nfinfo) \
+ (finfo.st_uid != nfinfo.st_uid || finfo.st_gid != nfinfo.st_gid)
+
/* Truncate the history file FNAME, leaving only LINES trailing lines.
If FNAME is NULL, then use ~/.history. Writes a new file and renames
it to the original name. Returns 0 on success, errno on failure. */
@@ -495,7 +521,7 @@ history_truncate_file (const char *fname, int lines)
{
char *buffer, *filename, *tempname, *bp, *bp1; /* bp1 == bp+1 */
int file, chars_read, rv, orig_lines, exists, r;
- struct stat finfo;
+ struct stat finfo, nfinfo;
size_t file_size;
history_lines_written_to_file = 0;
@@ -516,6 +542,9 @@ history_truncate_file (const char *fname, int lines)
}
exists = 1;
+ nfinfo.st_uid = finfo.st_uid;
+ nfinfo.st_gid = finfo.st_gid;
+
if (S_ISREG (finfo.st_mode) == 0)
{
close (file);
@@ -604,6 +633,9 @@ history_truncate_file (const char *fname, int lines)
if (write (file, bp, chars_read - (bp - buffer)) < 0)
rv = errno;
+ if (fstat (file, &nfinfo) < 0 && rv == 0)
+ rv = errno;
+
if (close (file) < 0 && rv == 0)
rv = errno;
}
@@ -620,6 +652,7 @@ history_truncate_file (const char *fname, int lines)
if (rv != 0)
{
+ rv = errno;
if (tempname)
unlink (tempname);
history_lines_written_to_file = 0;
@@ -630,7 +663,7 @@ history_truncate_file (const char *fname, int lines)
user is running this, it's a no-op. If the shell is running after sudo
with a shared history file, we don't want to leave the history file
owned by root. */
- if (rv == 0 && exists)
+ if (rv == 0 && exists && SHOULD_CHOWN (finfo, nfinfo))
r = chown (filename, finfo.st_uid, finfo.st_gid);
#endif
@@ -649,7 +682,7 @@ history_do_write (const char *filename, int nelements, int overwrite)
register int i;
char *output, *tempname, *histname;
int file, mode, rv, exists;
- struct stat finfo;
+ struct stat finfo, nfinfo;
#ifdef HISTORY_USE_MMAP
size_t cursize;
@@ -694,15 +727,11 @@ history_do_write (const char *filename, int nelements, int overwrite)
the_history = history_list ();
/* Calculate the total number of bytes to write. */
for (buffer_size = 0, i = history_length - nelements; i < history_length; i++)
-#if 0
- buffer_size += 2 + HISTENT_BYTES (the_history[i]);
-#else
{
if (history_write_timestamps && the_history[i]->timestamp && the_history[i]->timestamp[0])
buffer_size += strlen (the_history[i]->timestamp) + 1;
buffer_size += strlen (the_history[i]->line) + 1;
}
-#endif
/* Allocate the buffer, and fill it. */
#ifdef HISTORY_USE_MMAP
@@ -767,6 +796,7 @@ mmap_error:
if (rv != 0)
{
+ rv = errno;
if (tempname)
unlink (tempname);
history_lines_written_to_file = 0;
diff --git a/lib/readline/input.c b/lib/readline/input.c
index d4d57a81..61b0fde3 100644
--- a/lib/readline/input.c
+++ b/lib/readline/input.c
@@ -22,6 +22,8 @@
#define READLINE_LIBRARY
#if defined (__TANDEM)
+# define _XOPEN_SOURCE_EXTENDED 1
+# define _TANDEM_SOURCE 1
# include <floss.h>
#endif
@@ -347,8 +349,7 @@ _rl_input_available (void)
FD_ZERO (&exceptfds);
FD_SET (tty, &readfds);
FD_SET (tty, &exceptfds);
- timeout.tv_sec = 0;
- timeout.tv_usec = _keyboard_input_timeout;
+ USEC_TO_TIMEVAL (_keyboard_input_timeout, timeout);
return (select (tty + 1, &readfds, (fd_set *)NULL, &exceptfds, &timeout) > 0);
#else
@@ -368,6 +369,24 @@ _rl_input_available (void)
}
int
+_rl_nchars_available ()
+{
+ int chars_avail, fd, result;
+
+ chars_avail = 0;
+
+#if defined (FIONREAD)
+ fd = fileno (rl_instream);
+ errno = 0;
+ result = ioctl (fd, FIONREAD, &chars_avail);
+ if (result == -1 && errno == EIO)
+ return -1;
+#endif
+
+ return chars_avail;
+}
+
+int
_rl_input_queued (int t)
{
int old_timeout, r;
@@ -493,7 +512,7 @@ rl_read_key (void)
{
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); */
+/* fprintf(stderr, "rl_read_key: calling RL_CHECK_SIGNALS: _rl_caught_signal = %d\r\n", _rl_caught_signal); */
RL_CHECK_SIGNALS ();
}
}
@@ -596,6 +615,10 @@ handle_error:
else if (_rl_caught_signal == SIGINT)
#endif
RL_CHECK_SIGNALS ();
+#if defined (SIGTSTP)
+ else if (_rl_caught_signal == SIGTSTP)
+ RL_CHECK_SIGNALS ();
+#endif
/* non-keyboard-generated signals of interest */
#if defined (SIGWINCH)
else if (_rl_caught_signal == SIGWINCH)
@@ -631,9 +654,7 @@ _rl_read_mbchar (char *mbchar, int size)
mb_len = 0;
while (mb_len < size)
{
- RL_SETSTATE(RL_STATE_MOREINPUT);
- c = rl_read_key ();
- RL_UNSETSTATE(RL_STATE_MOREINPUT);
+ c = (mb_len == 0) ? _rl_bracketed_read_key () : rl_read_key ();
if (c < 0)
break;
diff --git a/lib/readline/isearch.c b/lib/readline/isearch.c
index d6c59041..080ba3cb 100644
--- a/lib/readline/isearch.c
+++ b/lib/readline/isearch.c
@@ -6,7 +6,7 @@
/* */
/* **************************************************************** */
-/* Copyright (C) 1987-2017 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2020 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.
@@ -185,11 +185,13 @@ rl_display_search (char *search_string, int flags, int where)
strcpy (message + msglen, "i-search)`");
msglen += 10;
- if (search_string)
+ if (search_string && *search_string)
{
strcpy (message + msglen, search_string);
msglen += searchlen;
}
+ else
+ _rl_optimize_redisplay ();
strcpy (message + msglen, "': ");
@@ -255,6 +257,9 @@ _rl_isearch_init (int direction)
_rl_iscxt = cxt; /* save globally */
+ /* experimental right now */
+ _rl_init_executing_keyseq ();
+
return cxt;
}
@@ -287,16 +292,22 @@ _rl_isearch_fini (_rl_search_cxt *cxt)
else
cxt->sline_index = strlen (rl_line_buffer);
rl_mark = cxt->save_mark;
+ rl_deactivate_mark ();
}
rl_point = cxt->sline_index;
/* Don't worry about where to put the mark here; rl_get_previous_history
- and rl_get_next_history take care of it. */
+ and rl_get_next_history take care of it.
+ If we want to highlight the search string, this is where to set the
+ point and mark to do it. */
_rl_fix_point (0);
+ rl_deactivate_mark ();
+/* _rl_optimize_redisplay (); */
rl_clear_message ();
}
+/* XXX - we could use _rl_bracketed_read_mbstring () here. */
int
_rl_search_getchar (_rl_search_cxt *cxt)
{
@@ -342,6 +353,24 @@ _rl_isearch_dispatch (_rl_search_cxt *cxt, int c)
return -1;
}
+ _rl_add_executing_keyseq (c);
+
+ /* XXX - experimental code to allow users to bracketed-paste into the search
+ string even when ESC is one of the isearch-terminators. Not perfect yet. */
+ if (_rl_enable_bracketed_paste && c == ESC && strchr (cxt->search_terminators, c) && (n = _rl_nchars_available ()) > (BRACK_PASTE_SLEN-1))
+ {
+ j = _rl_read_bracketed_paste_prefix (c);
+ if (j == 1)
+ {
+ cxt->lastc = -7; /* bracketed paste, see below */
+ goto opcode_dispatch;
+ }
+ else if (_rl_pushed_input_available ()) /* eat extra char we pushed back */
+ c = cxt->lastc = rl_read_key ();
+ else
+ c = cxt->lastc; /* last ditch */
+ }
+
/* If we are moving into a new keymap, modify cxt->keymap and go on.
This can be a problem if c == ESC and we want to terminate the
incremental search, so we check */
@@ -387,7 +416,18 @@ add_character:
/* Translate the keys we do something with to opcodes. */
if (c >= 0 && cxt->keymap[c].type == ISFUNC)
{
- f = cxt->keymap[c].function;
+ /* If we have a multibyte character, see if it's bound to something that
+ affects the search. */
+#if defined (HANDLE_MULTIBYTE)
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0 && cxt->mb[1])
+ f = rl_function_of_keyseq (cxt->mb, cxt->keymap, (int *)NULL);
+ else
+#endif
+ {
+ f = cxt->keymap[c].function;
+ if (f == rl_do_lowercase_version)
+ f = cxt->keymap[_rl_to_lower (c)].function;
+ }
if (f == rl_reverse_search_history)
cxt->lastc = (cxt->sflags & SF_REVERSE) ? -1 : -2;
@@ -454,9 +494,14 @@ add_character:
}
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? */
+ _rl_term_executing_keyseq (); /* should this go in the caller? */
+
+ _rl_pending_command.map = cxt->keymap;
+ _rl_pending_command.count = 1; /* XXX */
+ _rl_pending_command.key = cxt->lastc;
+ _rl_pending_command.func = f;
+ _rl_command_to_execute = &_rl_pending_command;
+
return (0);
}
}
@@ -502,6 +547,9 @@ add_character:
return (0);
}
+ _rl_init_executing_keyseq ();
+
+opcode_dispatch:
/* Now dispatch on the character. `Opcodes' affect the search string or
state. Other characters are added to the string. */
switch (cxt->lastc)
@@ -519,6 +567,7 @@ add_character:
rl_display_search (cxt->search_string, cxt->sflags, -1);
break;
}
+ /* XXX - restore keymap here? */
return (1);
}
else if ((cxt->sflags & SF_REVERSE) && cxt->sline_index >= 0)
@@ -566,9 +615,11 @@ add_character:
rl_replace_line (cxt->lines[cxt->save_line], 0);
rl_point = cxt->save_point;
rl_mark = cxt->save_mark;
+ rl_deactivate_mark ();
rl_restore_prompt();
rl_clear_message ();
+ _rl_fix_point (1); /* in case save_line and save_point are out of sync */
return -1;
case -5: /* C-W */
@@ -632,6 +683,8 @@ add_character:
free (paste);
break;
}
+ if (_rl_enable_active_region)
+ rl_activate_mark ();
if (cxt->search_string_index + pastelen + 1 >= cxt->search_string_size)
{
cxt->search_string_size += pastelen + 2;
@@ -736,11 +789,15 @@ add_character:
cxt->sline_index = (cxt->sflags & SF_REVERSE) ? cxt->sline_len - cxt->search_string_index : 0;
}
+ /* reset the keymaps for the next time through the loop */
+ cxt->keymap = cxt->okeymap = _rl_keymap;
+
if (cxt->sflags & SF_FAILED)
{
/* We cannot find the search string. Ding the bell. */
rl_ding ();
cxt->history_pos = cxt->last_found_line;
+ rl_deactivate_mark ();
rl_display_search (cxt->search_string, cxt->sflags, (cxt->history_pos == cxt->save_line) ? -1 : cxt->history_pos);
return 1;
}
@@ -752,7 +809,11 @@ add_character:
{
cxt->prev_line_found = cxt->lines[cxt->history_pos];
rl_replace_line (cxt->lines[cxt->history_pos], 0);
+ if (_rl_enable_active_region)
+ rl_activate_mark ();
rl_point = cxt->sline_index;
+ if (rl_mark_active_p () && cxt->search_string_index > 0)
+ rl_mark = rl_point + cxt->search_string_index;
cxt->last_found_line = cxt->history_pos;
rl_display_search (cxt->search_string, cxt->sflags, (cxt->history_pos == cxt->save_line) ? -1 : cxt->history_pos);
}
diff --git a/lib/readline/kill.c b/lib/readline/kill.c
index cf8ca932..50c3fdea 100644
--- a/lib/readline/kill.c
+++ b/lib/readline/kill.c
@@ -1,6 +1,6 @@
/* kill.c -- kill ring management. */
-/* Copyright (C) 1994-2017 Free Software Foundation, Inc.
+/* Copyright (C) 1994-2020 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.
@@ -408,6 +408,7 @@ region_kill_internal (int delete)
_rl_copy_to_kill_ring (text, rl_point < rl_mark);
}
+ _rl_fix_point (1);
_rl_last_command_was_kill++;
return 0;
}
@@ -427,8 +428,8 @@ rl_kill_region (int count, int key)
npoint = (rl_point < rl_mark) ? rl_point : rl_mark;
r = region_kill_internal (1);
- _rl_fix_point (1);
rl_point = npoint;
+ _rl_fix_point (1);
return r;
}
@@ -605,7 +606,7 @@ rl_yank_nth_arg_internal (int count, int key, int history_skip)
#if defined (VI_MODE)
/* Vi mode always inserts a space before yanking the argument, and it
inserts it right *after* rl_point. */
- if (rl_editing_mode == vi_mode)
+ if (rl_editing_mode == vi_mode && _rl_keymap == vi_movement_keymap)
{
rl_vi_append_mode (1, key);
rl_insert_text (" ");
@@ -668,8 +669,7 @@ rl_yank_last_arg (int count, int key)
/* Having read the special escape sequence denoting the beginning of a
`bracketed paste' sequence, read the rest of the pasted input until the
- closing sequence and insert the pasted text as a single unit without
- interpretation. */
+ closing sequence and return the pasted text. */
char *
_rl_bracketed_text (size_t *lenp)
{
@@ -715,6 +715,10 @@ _rl_bracketed_text (size_t *lenp)
return (buf);
}
+/* Having read the special escape sequence denoting the beginning of a
+ `bracketed paste' sequence, read the rest of the pasted input until the
+ closing sequence and insert the pasted text as a single unit without
+ interpretation. Temporarily highlight the inserted text. */
int
rl_bracketed_paste_begin (int count, int key)
{
@@ -723,12 +727,108 @@ rl_bracketed_paste_begin (int count, int key)
char *buf;
buf = _rl_bracketed_text (&len);
+ rl_mark = rl_point;
retval = rl_insert_text (buf) == len ? 0 : 1;
+ if (_rl_enable_active_region)
+ rl_activate_mark ();
xfree (buf);
return (retval);
}
+int
+_rl_read_bracketed_paste_prefix (int c)
+{
+ char pbuf[BRACK_PASTE_SLEN+1], *pbpref;
+ int key, ind, j;
+
+ pbpref = BRACK_PASTE_PREF; /* XXX - debugging */
+ if (c != pbpref[0])
+ return (0);
+ pbuf[ind = 0] = c;
+ while (ind < BRACK_PASTE_SLEN-1 &&
+ (RL_ISSTATE (RL_STATE_INPUTPENDING|RL_STATE_MACROINPUT) == 0) &&
+ _rl_pushed_input_available () == 0 &&
+ _rl_input_queued (0))
+ {
+ key = rl_read_key (); /* XXX - for now */
+ if (key < 0)
+ break;
+ pbuf[++ind] = key;
+ if (pbuf[ind] != pbpref[ind])
+ break;
+ }
+
+ if (ind < BRACK_PASTE_SLEN-1) /* read incomplete sequence */
+ {
+ while (ind >= 0)
+ _rl_unget_char (pbuf[ind--]);
+ return (key < 0 ? key : 0);
+ }
+ return (key < 0 ? key : 1);
+}
+
+/* Get a character from wherever we read input, handling input in bracketed
+ paste mode. If we don't have or use bracketed paste mode, this can be
+ used in place of rl_read_key(). */
+int
+_rl_bracketed_read_key ()
+{
+ int c, r;
+ char *pbuf;
+ size_t pblen;
+
+ RL_SETSTATE(RL_STATE_MOREINPUT);
+ c = rl_read_key ();
+ RL_UNSETSTATE(RL_STATE_MOREINPUT);
+
+ if (c < 0)
+ return -1;
+
+ /* read pasted data with bracketed-paste mode enabled. */
+ if (_rl_enable_bracketed_paste && c == ESC && (r = _rl_read_bracketed_paste_prefix (c)) == 1)
+ {
+ pbuf = _rl_bracketed_text (&pblen);
+ if (pblen == 0)
+ {
+ xfree (pbuf);
+ return 0; /* XXX */
+ }
+ c = (unsigned char)pbuf[0];
+ if (pblen > 1)
+ {
+ while (--pblen > 0)
+ _rl_unget_char ((unsigned char)pbuf[pblen]);
+ }
+ xfree (pbuf);
+ }
+
+ return c;
+}
+
+/* Get a character from wherever we read input, handling input in bracketed
+ paste mode. If we don't have or use bracketed paste mode, this can be
+ used in place of rl_read_key(). */
+int
+_rl_bracketed_read_mbstring (char *mb, int mlen)
+{
+ int c, r;
+
+ c = _rl_bracketed_read_key ();
+ if (c < 0)
+ return -1;
+
+#if defined (HANDLE_MULTIBYTE)
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ c = _rl_read_mbstring (c, mb, mlen);
+ else
+#endif
+ mb[0] = c;
+ mb[mlen] = '\0'; /* just in case */
+
+ return c;
+}
+
/* A special paste command for Windows users. */
#if defined (_WIN32)
#include <windows.h>
diff --git a/lib/readline/mbutil.c b/lib/readline/mbutil.c
index 17716357..dc62b4cc 100644
--- a/lib/readline/mbutil.c
+++ b/lib/readline/mbutil.c
@@ -1,6 +1,6 @@
/* mbutil.c -- readline multibyte character utility functions */
-/* Copyright (C) 2001-2017 Free Software Foundation, Inc.
+/* Copyright (C) 2001-2020 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.
@@ -86,7 +86,7 @@ int _rl_utf8locale = 0;
static int
_rl_utf8_mblen (const char *s, size_t n)
{
- unsigned char c, c1;
+ unsigned char c, c1, c2, c3;
if (s == 0)
return (0); /* no shift states */
@@ -101,25 +101,46 @@ _rl_utf8_mblen (const char *s, size_t n)
c1 = (unsigned char)s[1];
if (c < 0xe0)
{
- if (n >= 2 && (s[1] ^ 0x80) < 0x40)
+ if (n == 1)
+ return -2;
+ if (n >= 2 && (c1 ^ 0x80) < 0x40)
return 2;
}
else if (c < 0xf0)
{
- if (n >= 3
- && (s[1] ^ 0x80) < 0x40 && (s[2] ^ 0x80) < 0x40
+ if (n == 1)
+ return -2;
+ if ((c1 ^ 0x80) < 0x40
&& (c >= 0xe1 || c1 >= 0xa0)
&& (c != 0xed || c1 < 0xa0))
- return 3;
+ {
+ if (n == 2)
+ return -2;
+ c2 = (unsigned char)s[2];
+ if ((c2 ^ 0x80) < 0x40)
+ return 3;
+ }
}
- else if (c < 0xf8)
+ else if (c < 0xf4)
{
- if (n >= 4
- && (s[1] ^ 0x80) < 0x40 && (s[2] ^ 0x80) < 0x40
- && (s[3] ^ 0x80) < 0x40
+ if (n == 1)
+ return -2;
+ if (((c1 ^ 0x80) < 0x40)
&& (c >= 0xf1 || c1 >= 0x90)
&& (c < 0xf4 || (c == 0xf4 && c1 < 0x90)))
- return 4;
+ {
+ if (n == 2)
+ return -2;
+ c2 = (unsigned char)s[2];
+ if ((c2 ^ 0x80) < 0x40)
+ {
+ if (n == 3)
+ return -2;
+ c3 = (unsigned char)s[3];
+ if ((c3 ^ 0x80) < 0x40)
+ return 4;
+ }
+ }
}
}
/* invalid or incomplete multibyte character */
@@ -206,6 +227,66 @@ _rl_find_next_mbchar_internal (char *string, int seed, int count, int find_non_z
return point;
}
+static inline int
+_rl_test_nonzero (char *string, int ind, int len)
+{
+ size_t tmp;
+ wchar_t wc;
+ mbstate_t ps;
+
+ memset (&ps, 0, sizeof (mbstate_t));
+ tmp = mbrtowc (&wc, string + ind, len - ind, &ps);
+ /* treat invalid multibyte sequences as non-zero-width */
+ return (MB_INVALIDCH (tmp) || MB_NULLWCH (tmp) || WCWIDTH (wc) > 0);
+}
+
+/* experimental -- needs to handle zero-width characters better */
+static int
+_rl_find_prev_utf8char (char *string, int seed, int find_non_zero)
+{
+ char *s;
+ unsigned char b;
+ int save, prev;
+ size_t len;
+
+ if (find_non_zero)
+ len = RL_STRLEN (string);
+
+ prev = seed - 1;
+ while (prev >= 0)
+ {
+ b = (unsigned char)string[prev];
+ if (UTF8_SINGLEBYTE (b))
+ return (prev);
+
+ save = prev;
+
+ /* Move back until we're not in the middle of a multibyte char */
+ if (UTF8_MBCHAR (b))
+ {
+ while (prev > 0 && (b = (unsigned char)string[--prev]) && UTF8_MBCHAR (b))
+ ;
+ }
+
+ if (UTF8_MBFIRSTCHAR (b))
+ {
+ if (find_non_zero)
+ {
+ if (_rl_test_nonzero (string, prev, len))
+ return (prev);
+ else /* valid but WCWIDTH (wc) == 0 */
+ prev = prev - 1;
+ }
+ else
+ return (prev);
+ }
+ else
+ return (save); /* invalid utf-8 multibyte sequence */
+ }
+
+ return ((prev < 0) ? 0 : prev);
+}
+
/*static*/ int
_rl_find_prev_mbchar_internal (char *string, int seed, int find_non_zero)
{
@@ -214,6 +295,9 @@ _rl_find_prev_mbchar_internal (char *string, int seed, int find_non_zero)
size_t tmp;
wchar_t wc;
+ if (_rl_utf8locale)
+ return (_rl_find_prev_utf8char (string, seed, find_non_zero));
+
memset(&ps, 0, sizeof(mbstate_t));
length = strlen(string);
diff --git a/lib/readline/misc.c b/lib/readline/misc.c
index 42005b0c..3d9a674c 100644
--- a/lib/readline/misc.c
+++ b/lib/readline/misc.c
@@ -1,6 +1,6 @@
/* misc.c -- miscellaneous bindable readline functions. */
-/* Copyright (C) 1987-2017 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2019 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.
@@ -138,9 +138,7 @@ _rl_arg_dispatch (_rl_arg_cxt cxt, int c)
}
else
{
- RL_SETSTATE(RL_STATE_MOREINPUT);
- key = rl_read_key ();
- RL_UNSETSTATE(RL_STATE_MOREINPUT);
+ key = _rl_bracketed_read_key ();
rl_restore_prompt ();
rl_clear_message ();
RL_UNSETSTATE(RL_STATE_NUMERICARG);
@@ -435,7 +433,7 @@ rl_replace_from_history (HIST_ENTRY *entry, int flags)
intended to be called while actively editing, and the current line is
not assumed to have been added to the history list. */
void
-_rl_revert_all_lines (void)
+_rl_revert_previous_lines (void)
{
int hpos;
HIST_ENTRY *entry;
@@ -479,6 +477,19 @@ _rl_revert_all_lines (void)
xfree (lbuf);
}
+/* Revert all lines in the history by making sure we are at the end of the
+ history before calling _rl_revert_previous_lines() */
+void
+_rl_revert_all_lines (void)
+{
+ int pos;
+
+ pos = where_history ();
+ using_history ();
+ _rl_revert_previous_lines ();
+ history_set_pos (pos);
+}
+
/* 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
@@ -626,6 +637,48 @@ rl_get_previous_history (int count, int key)
return 0;
}
+/* The equivalent of the Korn shell C-o operate-and-get-next-history-line
+ editing command. */
+
+/* This could stand to be global to the readline library */
+static rl_hook_func_t *_rl_saved_internal_startup_hook = 0;
+static int saved_history_logical_offset = -1;
+
+#define HISTORY_FULL() (history_is_stifled () && history_length >= history_max_entries)
+
+static int
+set_saved_history ()
+{
+ int absolute_offset, count;
+
+ if (saved_history_logical_offset >= 0)
+ {
+ absolute_offset = saved_history_logical_offset - history_base;
+ count = where_history () - absolute_offset;
+ rl_get_previous_history (count, 0);
+ }
+ saved_history_logical_offset = -1;
+ _rl_internal_startup_hook = _rl_saved_internal_startup_hook;
+
+ return (0);
+}
+
+int
+rl_operate_and_get_next (count, c)
+ int count, c;
+{
+ /* Accept the current line. */
+ rl_newline (1, c);
+
+ saved_history_logical_offset = rl_explicit_arg ? count : where_history () + history_base + 1;
+
+
+ _rl_saved_internal_startup_hook = _rl_internal_startup_hook;
+ _rl_internal_startup_hook = set_saved_history;
+
+ return 0;
+}
+
/* **************************************************************** */
/* */
/* Editing Modes */
diff --git a/lib/readline/posixdir.h b/lib/readline/posixdir.h
index 0921c5d7..af5be801 100644
--- a/lib/readline/posixdir.h
+++ b/lib/readline/posixdir.h
@@ -46,7 +46,7 @@
# define D_NAMLEN(d) ((d)->d_namlen)
#endif /* !HAVE_DIRENT_H */
-/* The bash code fairly consistenly uses d_fileno; make sure it's available */
+/* The bash code fairly consistently 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
diff --git a/lib/readline/posixstat.h b/lib/readline/posixstat.h
index 3eb7f290..b6077860 100644
--- a/lib/readline/posixstat.h
+++ b/lib/readline/posixstat.h
@@ -1,7 +1,7 @@
/* posixstat.h -- Posix stat(2) definitions for systems that
don't have them. */
-/* Copyright (C) 1987,1991 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2019 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -132,6 +132,26 @@
# define S_IRWXU (S_IRUSR | S_IWUSR | S_IXUSR)
# define S_IRWXG (S_IRGRP | S_IWGRP | S_IXGRP)
# define S_IRWXO (S_IROTH | S_IWOTH | S_IXOTH)
+#else /* !S_IRWXU */
+ /* S_IRWXU is defined, but "group" and "other" bits might not be
+ (happens in certain versions of MinGW). */
+# if !defined (S_IRGRP)
+# define S_IRGRP (S_IREAD >> 3) /* read, group */
+# define S_IWGRP (S_IWRITE >> 3) /* write, group */
+# define S_IXGRP (S_IEXEC >> 3) /* execute, group */
+# endif /* !S_IRGRP */
+
+# if !defined (S_IROTH)
+# define S_IROTH (S_IREAD >> 6) /* read, other */
+# define S_IWOTH (S_IWRITE >> 6) /* write, other */
+# define S_IXOTH (S_IEXEC >> 6) /* execute, other */
+# endif /* !S_IROTH */
+# if !defined (S_IRWXG)
+# define S_IRWXG (S_IRGRP | S_IWGRP | S_IXGRP)
+# endif
+# if !defined (S_IRWXO)
+# define S_IRWXO (S_IROTH | S_IWOTH | S_IXOTH)
+# endif
#endif /* !S_IRWXU */
/* These are non-standard, but are used in builtins.c$symbolic_umask() */
diff --git a/lib/readline/readline.c b/lib/readline/readline.c
index 678f989c..e61d188b 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-2017 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2020 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.
@@ -73,11 +73,11 @@ extern int errno;
#include "xmalloc.h"
#ifndef RL_LIBRARY_VERSION
-# define RL_LIBRARY_VERSION "5.1"
+# define RL_LIBRARY_VERSION "8.0"
#endif
#ifndef RL_READLINE_VERSION
-# define RL_READLINE_VERSION 0x0501
+# define RL_READLINE_VERSION 0x0800
#endif
extern void _rl_free_history_entry PARAMS((HIST_ENTRY *));
@@ -199,6 +199,10 @@ int rl_key_sequence_length = 0;
before readline_internal_setup () prints the first prompt. */
rl_hook_func_t *rl_startup_hook = (rl_hook_func_t *)NULL;
+/* Any readline function can set this and have it run just before the user's
+ rl_startup_hook. */
+rl_hook_func_t *_rl_internal_startup_hook = (rl_hook_func_t *)NULL;
+
/* If non-zero, this is the address of a function to call just before
readline_internal_setup () returns and readline_internal starts
reading input characters. */
@@ -258,6 +262,9 @@ int rl_executing_key;
char *rl_executing_keyseq = 0;
int _rl_executing_keyseq_size = 0;
+struct _rl_cmd _rl_pending_command;
+struct _rl_cmd *_rl_command_to_execute = (struct _rl_cmd *)NULL;
+
/* Timeout (specified in milliseconds) when reading characters making up an
ambiguous multiple-key sequence */
int _rl_keyseq_timeout = 500;
@@ -314,7 +321,8 @@ int _rl_show_mode_in_prompt = 0;
/* Non-zero means to attempt to put the terminal in `bracketed paste mode',
where it will prefix pasted text with an escape sequence and send
another to mark the end of the paste. */
-int _rl_enable_bracketed_paste = 0;
+int _rl_enable_bracketed_paste = BRACKETED_PASTE_DEFAULT;
+int _rl_enable_active_region = BRACKETED_PASTE_DEFAULT;
/* **************************************************************** */
/* */
@@ -417,6 +425,11 @@ readline_internal_setup (void)
if (rl_startup_hook)
(*rl_startup_hook) ();
+ if (_rl_internal_startup_hook)
+ (*_rl_internal_startup_hook) ();
+
+ rl_deactivate_mark ();
+
#if defined (VI_MODE)
if (rl_editing_mode == vi_mode)
rl_vi_insertion_mode (1, 'i'); /* don't want to reset last */
@@ -632,12 +645,34 @@ readline_internal_charloop (void)
r = _rl_dispatch ((unsigned char)c, _rl_keymap);
RL_CHECK_SIGNALS ();
+ if (_rl_command_to_execute)
+ {
+ (*rl_redisplay_function) ();
+
+ rl_executing_keymap = _rl_command_to_execute->map;
+ rl_executing_key = _rl_command_to_execute->key;
+
+ rl_dispatching = 1;
+ RL_SETSTATE(RL_STATE_DISPATCHING);
+ r = (*(_rl_command_to_execute->func)) (_rl_command_to_execute->count, _rl_command_to_execute->key);
+ _rl_command_to_execute = 0;
+ RL_UNSETSTATE(RL_STATE_DISPATCHING);
+ rl_dispatching = 0;
+
+ RL_CHECK_SIGNALS ();
+ }
+
/* If there was no change in _rl_last_command_was_kill, then no kill
has taken place. Note that if input is pending we are reading
a prefix command, so nothing has changed yet. */
if (rl_pending_input == 0 && lk == _rl_last_command_was_kill)
_rl_last_command_was_kill = 0;
+ if (_rl_keep_mark_active)
+ _rl_keep_mark_active = 0;
+ else if (rl_mark_active_p ())
+ rl_deactivate_mark ();
+
_rl_internal_char_cleanup ();
#if defined (READLINE_CALLBACKS)
@@ -856,7 +891,11 @@ _rl_dispatch_subseq (register int key, Keymap map, int got_subseq)
/* If we have input pending, then the last command was a prefix
command. Don't change the state of rl_last_func. Otherwise,
remember the last command executed in this variable. */
+#if defined (VI_MODE)
+ if (rl_pending_input == 0 && map[key].function != rl_digit_argument && map[key].function != rl_vi_arg_digit)
+#else
if (rl_pending_input == 0 && map[key].function != rl_digit_argument)
+#endif
rl_last_func = map[key].function;
RL_CHECK_SIGNALS ();
@@ -870,6 +909,8 @@ _rl_dispatch_subseq (register int key, Keymap map, int got_subseq)
_rl_prev_macro_key ();
else
_rl_unget_char (key);
+ if (rl_key_sequence_length > 0)
+ rl_executing_keyseq[--rl_key_sequence_length] = '\0';
return -2;
}
else if (got_subseq)
@@ -882,6 +923,8 @@ _rl_dispatch_subseq (register int key, Keymap map, int got_subseq)
_rl_prev_macro_key ();
else
_rl_unget_char (key);
+ if (rl_key_sequence_length > 0)
+ rl_executing_keyseq[--rl_key_sequence_length] = '\0';
return -1;
}
else
@@ -974,7 +1017,11 @@ _rl_dispatch_subseq (register int key, Keymap map, int got_subseq)
_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));
+ {
+ if (rl_key_sequence_length > 0)
+ rl_executing_keyseq[--rl_key_sequence_length] = '\0';
+ return (_rl_subseq_result (-2, map, key, got_subseq));
+ }
newkey = _rl_subseq_getchar (key);
if (newkey < 0)
@@ -1065,6 +1112,8 @@ _rl_subseq_result (int r, Keymap map, int key, int got_subseq)
_rl_prev_macro_key ();
else
_rl_unget_char (key);
+ if (rl_key_sequence_length > 0)
+ rl_executing_keyseq[--rl_key_sequence_length] = '\0';
_rl_dispatching_keymap = map;
return -2;
}
@@ -1075,6 +1124,8 @@ _rl_subseq_result (int r, Keymap map, int key, int got_subseq)
_rl_prev_macro_key ();
else
_rl_unget_char (key);
+ if (rl_key_sequence_length > 0)
+ rl_executing_keyseq[--rl_key_sequence_length] = '\0';
_rl_dispatching_keymap = map;
return -1;
}
@@ -1241,7 +1292,7 @@ readline_initialize_everything (void)
rl_executing_keyseq = malloc (_rl_executing_keyseq_size = 16);
if (rl_executing_keyseq)
- rl_executing_keyseq[0] = '\0';
+ rl_executing_keyseq[rl_key_sequence_length = 0] = '\0';
}
/* If this system allows us to look at the values of the regular
@@ -1356,9 +1407,12 @@ bind_bracketed_paste_prefix (void)
_rl_keymap = emacs_standard_keymap;
rl_bind_keyseq_if_unbound (BRACK_PASTE_PREF, rl_bracketed_paste_begin);
-
+
+#if defined (VI_MODE)
_rl_keymap = vi_insertion_keymap;
rl_bind_keyseq_if_unbound (BRACK_PASTE_PREF, rl_bracketed_paste_begin);
+ /* XXX - is there a reason to do this in the vi command keymap? */
+#endif
_rl_keymap = xkeymap;
}
@@ -1446,5 +1500,35 @@ rl_restore_state (struct readline_state *sp)
rl_attempted_completion_function = sp->attemptfunc;
rl_completer_word_break_characters = sp->wordbreakchars;
+ rl_deactivate_mark ();
+
return (0);
}
+
+/* Functions to manage the string that is the current key sequence. */
+
+void
+_rl_init_executing_keyseq (void)
+{
+ rl_executing_keyseq[rl_key_sequence_length = 0] = '\0';
+}
+
+void
+_rl_term_executing_keyseq (void)
+{
+ rl_executing_keyseq[rl_key_sequence_length] = '\0';
+}
+
+void
+_rl_end_executing_keyseq (void)
+{
+ if (rl_key_sequence_length > 0)
+ rl_executing_keyseq[--rl_key_sequence_length] = '\0';
+}
+
+void
+_rl_add_executing_keyseq (int key)
+{
+ RESIZE_KEYSEQ_BUFFER ();
+ rl_executing_keyseq[rl_key_sequence_length++] = key;
+}
diff --git a/lib/readline/readline.h b/lib/readline/readline.h
index da782716..78fa39d0 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-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2020 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 0x0800 /* Readline 8.0 */
+#define RL_READLINE_VERSION 0x0801 /* Readline 8.0 */
#define RL_VERSION_MAJOR 8
-#define RL_VERSION_MINOR 0
+#define RL_VERSION_MINOR 1
/* Readline data structures. */
@@ -95,6 +95,7 @@ extern int rl_forward_word PARAMS((int, int));
extern int rl_backward_word PARAMS((int, int));
extern int rl_refresh_line PARAMS((int, int));
extern int rl_clear_screen PARAMS((int, int));
+extern int rl_clear_display PARAMS((int, int));
extern int rl_skip_csi_sequence PARAMS((int, int));
extern int rl_arrow_keys PARAMS((int, int));
@@ -132,6 +133,7 @@ extern int rl_beginning_of_history PARAMS((int, int));
extern int rl_end_of_history PARAMS((int, int));
extern int rl_get_next_history PARAMS((int, int));
extern int rl_get_previous_history PARAMS((int, int));
+extern int rl_operate_and_get_next PARAMS((int, int));
/* Bindable commands for managing the mark and region. */
extern int rl_set_mark PARAMS((int, int));
@@ -392,6 +394,14 @@ extern int rl_clear_message PARAMS((void));
extern int rl_reset_line_state PARAMS((void));
extern int rl_crlf PARAMS((void));
+/* Functions to manage the mark and region, especially the notion of an
+ active mark and an active region. */
+extern void rl_keep_mark_active PARAMS((void));
+
+extern void rl_activate_mark PARAMS((void));
+extern void rl_deactivate_mark PARAMS((void));
+extern int rl_mark_active_p PARAMS((void));
+
#if defined (USE_VARARGS) && defined (PREFER_STDARG)
extern int rl_message (const char *, ...) __attribute__((__format__ (printf, 1, 2)));
#else
diff --git a/lib/readline/rlmbutil.h b/lib/readline/rlmbutil.h
index 6fd03f6a..4d3e9070 100644
--- a/lib/readline/rlmbutil.h
+++ b/lib/readline/rlmbutil.h
@@ -28,7 +28,7 @@
/* check multibyte capability for I18N code */
/************************************************/
-/* For platforms which support the ISO C amendement 1 functionality we
+/* For platforms which support the ISO C amendment 1 functionality we
support user defined character classes. */
/* Solaris 2.5 has a bug: <wchar.h> must be included before <wctype.h>. */
#if defined (HAVE_WCTYPE_H) && defined (HAVE_WCHAR_H) && defined (HAVE_LOCALE_H)
diff --git a/lib/readline/rlprivate.h b/lib/readline/rlprivate.h
index e85e4d81..23ab2d8c 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-2015 Free Software Foundation, Inc.
+/* Copyright (C) 1999-2020 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.
@@ -65,7 +65,8 @@
#define SF_FOUND 0x02
#define SF_FAILED 0x04
#define SF_CHGKMAP 0x08
-#define SF_PATTERN 0x10 /* unused so far */
+#define SF_PATTERN 0x10
+#define SF_NOCASE 0x20 /* unused so far */
typedef struct __rl_search_context
{
@@ -109,6 +110,15 @@ typedef struct __rl_search_context
char *search_terminators;
} _rl_search_cxt;
+struct _rl_cmd {
+ Keymap map;
+ int count;
+ int key;
+ rl_command_func_t *func;
+};
+extern struct _rl_cmd _rl_pending_command;
+extern struct _rl_cmd *_rl_command_to_execute;
+
/* Callback data for reading numeric arguments */
#define NUM_SAWMINUS 0x01
#define NUM_SAWDIGITS 0x02
@@ -267,23 +277,25 @@ 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));
extern void _rl_restore_prompt PARAMS((void));
extern char *_rl_make_prompt_for_search PARAMS((int));
extern void _rl_erase_at_end_of_line PARAMS((int));
extern void _rl_clear_to_eol PARAMS((int));
-extern void _rl_clear_screen PARAMS((void));
+extern void _rl_clear_screen PARAMS((int));
extern void _rl_update_final PARAMS((void));
+extern void _rl_optimize_redisplay PARAMS((void));
extern void _rl_redisplay_after_sigwinch PARAMS((void));
extern void _rl_clean_up_for_exit PARAMS((void));
extern void _rl_erase_entire_line PARAMS((void));
extern int _rl_current_display_line PARAMS((void));
+extern void _rl_refresh_line PARAMS((void));
/* input.c */
extern int _rl_any_typein PARAMS((void));
extern int _rl_input_available PARAMS((void));
+extern int _rl_nchars_available PARAMS((void));
extern int _rl_input_queued PARAMS((int));
extern void _rl_insert_typein PARAMS((int));
extern int _rl_unget_char PARAMS((int));
@@ -300,6 +312,10 @@ extern int _rl_isearch_cleanup PARAMS((_rl_search_cxt *, int));
extern int _rl_search_getchar PARAMS((_rl_search_cxt *));
/* kill.c */
+#ifndef BRACKETED_PASTE_DEFAULT
+# define BRACKETED_PASTE_DEFAULT 1 /* XXX - for now */
+#endif
+
#define BRACK_PASTE_PREF "\033[200~"
#define BRACK_PASTE_SUFF "\033[201~"
@@ -309,7 +325,10 @@ extern int _rl_search_getchar PARAMS((_rl_search_cxt *));
#define BRACK_PASTE_INIT "\033[?2004h"
#define BRACK_PASTE_FINI "\033[?2004l\r"
+extern int _rl_read_bracketed_paste_prefix PARAMS((int));
extern char *_rl_bracketed_text PARAMS((size_t *));
+extern int _rl_bracketed_read_key PARAMS((void));
+extern int _rl_bracketed_read_mbstring PARAMS((char *, int));
/* macro.c */
extern void _rl_with_macro_input PARAMS((char *));
@@ -332,6 +351,7 @@ extern void _rl_start_using_history PARAMS((void));
extern int _rl_free_saved_history_line PARAMS((void));
extern void _rl_set_insert_mode PARAMS((int, int));
+extern void _rl_revert_previous_lines PARAMS((void));
extern void _rl_revert_all_lines PARAMS((void));
/* nls.c */
@@ -348,6 +368,11 @@ extern int _rl_dispatch PARAMS((int, Keymap));
extern int _rl_dispatch_subseq PARAMS((int, Keymap, int));
extern void _rl_internal_char_cleanup PARAMS((void));
+extern void _rl_init_executing_keyseq PARAMS((void));
+extern void _rl_term_executing_keyseq PARAMS((void));
+extern void _rl_end_executing_keyseq PARAMS((void));
+extern void _rl_add_executing_keyseq PARAMS((int));
+
/* rltty.c */
extern int _rl_disable_tty_signals PARAMS((void));
extern int _rl_restore_tty_signals PARAMS((void));
@@ -373,15 +398,19 @@ extern void _rl_output_character_function PARAMS((int));
#else
extern int _rl_output_character_function PARAMS((int));
#endif
+extern void _rl_cr PARAMS((void));
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));
+extern void _rl_standout_on PARAMS((void));
+extern void _rl_standout_off PARAMS((void));
/* text.c */
extern void _rl_fix_point PARAMS((int));
+extern void _rl_fix_mark PARAMS((void));
extern int _rl_replace_text PARAMS((const char *, int, int));
extern int _rl_forward_char_internal PARAMS((int));
extern int _rl_backward_char_internal PARAMS((int));
@@ -507,6 +536,7 @@ extern int _rl_revert_all_at_newline;
extern int _rl_echo_control_chars;
extern int _rl_show_mode_in_prompt;
extern int _rl_enable_bracketed_paste;
+extern int _rl_enable_active_region;
extern char *_rl_comment_begin;
extern unsigned char _rl_parsing_conditionalized_out;
extern Keymap _rl_keymap;
@@ -521,11 +551,12 @@ extern int _rl_keyseq_timeout;
extern int _rl_executing_keyseq_size;
+extern rl_hook_func_t *_rl_internal_startup_hook;
+
/* search.c */
extern _rl_search_cxt *_rl_nscxt;
/* signals.c */
-extern int _rl_interrupt_immediately;
extern int volatile _rl_caught_signal;
extern _rl_sigcleanup_func_t *_rl_sigcleanup;
@@ -560,6 +591,7 @@ extern int _rl_term_autowrap;
/* text.c */
extern int _rl_optimize_typeahead;
+extern int _rl_keep_mark_active;
/* undo.c */
extern int _rl_doing_an_undo;
diff --git a/lib/readline/search.c b/lib/readline/search.c
index c9c1f5d1..38a29361 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-2017 Free Software Foundation, Inc.
+/* Copyright (C) 1992-2020 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.
@@ -159,7 +159,7 @@ noninc_search_from_pos (char *string, int pos, int dir, int flags, int *ncp)
static int
noninc_dosearch (char *string, int dir, int flags)
{
- int oldpos, pos;
+ int oldpos, pos, ind;
HIST_ENTRY *entry;
if (string == 0 || *string == '\0' || noninc_history_pos < 0)
@@ -168,7 +168,7 @@ noninc_dosearch (char *string, int dir, int flags)
return 0;
}
- pos = noninc_search_from_pos (string, noninc_history_pos + dir, dir, flags, (int *)0);
+ pos = noninc_search_from_pos (string, noninc_history_pos + dir, dir, flags, &ind);
if (pos == -1)
{
/* Search failed, current history position unchanged. */
@@ -192,8 +192,19 @@ noninc_dosearch (char *string, int dir, int flags)
make_history_line_current (entry);
- rl_point = 0;
- rl_mark = rl_end;
+ if (_rl_enable_active_region && ((flags & SF_PATTERN) == 0) && ind > 0 && ind < rl_end)
+ {
+ rl_point = ind;
+ rl_mark = ind + strlen (string);
+ if (rl_mark > rl_end)
+ rl_mark = rl_end; /* can't happen? */
+ rl_activate_mark ();
+ }
+ else
+ {
+ rl_point = 0;
+ rl_mark = rl_end;
+ }
rl_clear_message ();
return 1;
@@ -256,6 +267,7 @@ _rl_nsearch_abort (_rl_search_cxt *cxt)
rl_clear_message ();
rl_point = cxt->save_point;
rl_mark = cxt->save_mark;
+ _rl_fix_point (1);
rl_restore_prompt ();
RL_UNSETSTATE (RL_STATE_NSEARCH);
@@ -267,6 +279,8 @@ _rl_nsearch_abort (_rl_search_cxt *cxt)
static int
_rl_nsearch_dispatch (_rl_search_cxt *cxt, int c)
{
+ int n;
+
if (c < 0)
c = CTRL ('C');
@@ -300,6 +314,28 @@ _rl_nsearch_dispatch (_rl_search_cxt *cxt, int c)
_rl_nsearch_abort (cxt);
return -1;
+ case ESC:
+ /* XXX - experimental code to allow users to bracketed-paste into the
+ search string. Similar code is in isearch.c:_rl_isearch_dispatch().
+ The difference here is that the bracketed paste sometimes doesn't
+ paste everything, so checking for the prefix and the suffix in the
+ input queue doesn't work well. We just have to check to see if the
+ number of chars in the input queue is enough for the bracketed paste
+ prefix and hope for the best. */
+ if (_rl_enable_bracketed_paste && ((n = _rl_nchars_available ()) >= (BRACK_PASTE_SLEN-1)))
+ {
+ if (_rl_read_bracketed_paste_prefix (c) == 1)
+ rl_bracketed_paste_begin (1, c);
+ else
+ {
+ c = rl_read_key (); /* get the ESC that got pushed back */
+ _rl_insert_char (1, c);
+ }
+ }
+ else
+ _rl_insert_char (1, c);
+ break;
+
default:
#if defined (HANDLE_MULTIBYTE)
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
@@ -311,6 +347,7 @@ _rl_nsearch_dispatch (_rl_search_cxt *cxt, int c)
}
(*rl_redisplay_function) ();
+ rl_deactivate_mark ();
return 1;
}
diff --git a/lib/readline/signals.c b/lib/readline/signals.c
index 76c5c473..f9174ab8 100644
--- a/lib/readline/signals.c
+++ b/lib/readline/signals.c
@@ -99,7 +99,6 @@ int rl_catch_sigwinch = 0; /* for the readline state struct in readline.c */
#endif
/* Private variables. */
-int _rl_interrupt_immediately = 0;
int volatile _rl_caught_signal = 0; /* should be sig_atomic_t, but that requires including <signal.h> everywhere */
/* If non-zero, print characters corresponding to received signals as long as
@@ -136,7 +135,7 @@ void *_rl_sigcleanarg;
/* Readline signal handler functions. */
-/* Called from RL_CHECK_SIGNALS() macro */
+/* Called from RL_CHECK_SIGNALS() macro to run signal handling code. */
RETSIGTYPE
_rl_signal_handler (int sig)
{
@@ -145,6 +144,8 @@ _rl_signal_handler (int sig)
#if defined (SIGWINCH)
if (sig == SIGWINCH)
{
+ RL_SETSTATE(RL_STATE_SIGHANDLER);
+
rl_resize_terminal ();
/* XXX - experimental for now */
/* Call a signal hook because though we called the original signal handler
@@ -152,6 +153,8 @@ _rl_signal_handler (int sig)
ourselves. */
if (rl_signal_event_hook)
(*rl_signal_event_hook) ();
+
+ RL_UNSETSTATE(RL_STATE_SIGHANDLER);
}
else
#endif
@@ -163,22 +166,20 @@ _rl_signal_handler (int sig)
static RETSIGTYPE
rl_signal_handler (int sig)
{
- if (_rl_interrupt_immediately)
- {
- _rl_interrupt_immediately = 0;
- _rl_handle_signal (sig);
- }
- else
- _rl_caught_signal = sig;
-
+ _rl_caught_signal = sig;
SIGHANDLER_RETURN;
}
+/* This is called to handle a signal when it is safe to do so (out of the
+ signal handler execution path). Called by _rl_signal_handler for all the
+ signals readline catches except SIGWINCH. */
static RETSIGTYPE
_rl_handle_signal (int sig)
{
+ int block_sig;
+
#if defined (HAVE_POSIX_SIGNALS)
- sigset_t set;
+ sigset_t set, oset;
#else /* !HAVE_POSIX_SIGNALS */
# if defined (HAVE_BSD_SIGNALS)
long omask;
@@ -208,7 +209,16 @@ _rl_handle_signal (int sig)
_rl_sigcleanup = 0;
_rl_sigcleanarg = 0;
}
-
+
+#if defined (HAVE_POSIX_SIGNALS)
+ /* Get the current set of blocked signals. If we want to block a signal for
+ the duration of the cleanup functions, make sure to add it to SET and
+ set block_sig = 1 (see the SIGHUP case below). */
+ block_sig = 0; /* sentinel to block signals with sigprocmask */
+ sigemptyset (&set);
+ sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &set);
+#endif
+
switch (sig)
{
case SIGINT:
@@ -223,38 +233,60 @@ _rl_handle_signal (int sig)
#if defined (SIGTSTP)
case SIGTSTP:
case SIGTTIN:
+ case SIGTTOU:
# if defined (HAVE_POSIX_SIGNALS)
/* Block SIGTTOU so we can restore the terminal settings to something
sane without stopping on SIGTTOU if we have been placed into the
background. Even trying to get the current terminal pgrp with
- tcgetpgrp() will generate SIGTTOU, so we don't bother. Don't bother
- doing this if we've been stopped on SIGTTOU; it's aready too late. */
- sigemptyset (&set);
+ tcgetpgrp() will generate SIGTTOU, so we don't bother. We still do
+ this even if we've been stopped on SIGTTOU, since we handle signals
+ when we have returned from the signal handler and the signal is no
+ longer blocked. */
sigaddset (&set, SIGTTOU);
- sigprocmask (SIG_BLOCK, &set, (sigset_t *)NULL);
+ block_sig = 1;
# endif
- case SIGTTOU:
#endif /* SIGTSTP */
- case SIGTERM:
+ /* Any signals that should be blocked during cleanup should go here. */
#if defined (SIGHUP)
case SIGHUP:
-#endif
+# if defined (_AIX)
+ if (block_sig == 0)
+ {
+ sigaddset (&set, sig);
+ block_sig = 1;
+ }
+# endif // _AIX
+#endif
+ /* Signals that don't require blocking during cleanup should go here. */
+ case SIGTERM:
#if defined (SIGALRM)
case SIGALRM:
#endif
#if defined (SIGQUIT)
case SIGQUIT:
#endif
+
+ if (block_sig)
+ sigprocmask (SIG_BLOCK, &set, &oset);
+
rl_echo_signal_char (sig);
rl_cleanup_after_signal ();
+ /* At this point, the application's signal handler, if any, is the
+ current handler. */
+
#if defined (HAVE_POSIX_SIGNALS)
-# if defined (SIGTSTP)
- /* Unblock SIGTTOU blocked above */
- if (sig == SIGTTIN || sig == SIGTSTP)
- sigprocmask (SIG_UNBLOCK, &set, (sigset_t *)NULL);
-# endif
+ /* Unblock any signal(s) blocked above */
+ if (block_sig)
+ sigprocmask (SIG_UNBLOCK, &oset, (sigset_t *)NULL);
+#endif
+ /* We don't have to bother unblocking the signal because we are not
+ running in a signal handler context. */
+#if 0
+#if defined (HAVE_POSIX_SIGNALS)
+ /* Make sure this signal is not blocked when we resend it to the
+ calling application. */
sigemptyset (&set);
sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &set);
sigdelset (&set, sig);
@@ -263,6 +295,7 @@ _rl_handle_signal (int sig)
omask = sigblock (0);
# endif /* HAVE_BSD_SIGNALS */
#endif /* !HAVE_POSIX_SIGNALS */
+#endif
#if defined (__EMX__)
signal (sig, SIG_ACK);
@@ -274,7 +307,10 @@ _rl_handle_signal (int sig)
raise (sig); /* assume we have raise */
#endif
- /* Let the signal that we just sent through. */
+ /* We don't need to modify the signal mask now that this is not run in
+ a signal handler context. */
+#if 0
+ /* Let the signal that we just sent through if it is blocked. */
#if defined (HAVE_POSIX_SIGNALS)
sigprocmask (SIG_SETMASK, &set, (sigset_t *)NULL);
#else /* !HAVE_POSIX_SIGNALS */
@@ -282,6 +318,7 @@ _rl_handle_signal (int sig)
sigsetmask (omask & ~(sigmask (sig)));
# endif /* HAVE_BSD_SIGNALS */
#endif /* !HAVE_POSIX_SIGNALS */
+#endif
rl_reset_after_signal ();
}
diff --git a/lib/readline/terminal.c b/lib/readline/terminal.c
index e5573897..05415dc4 100644
--- a/lib/readline/terminal.c
+++ b/lib/readline/terminal.c
@@ -152,6 +152,10 @@ static int term_has_meta;
static char *_rl_term_mm;
static char *_rl_term_mo;
+/* The sequences to enter and exit standout mode. */
+static char *_rl_term_so;
+static char *_rl_term_se;
+
/* The key sequences output by the arrow keys, if this terminal has any. */
static char *_rl_term_ku;
static char *_rl_term_kd;
@@ -177,6 +181,19 @@ static char *_rl_term_kI;
static char *_rl_term_vs; /* very visible */
static char *_rl_term_ve; /* normal */
+/* It's not clear how HPUX is so broken here. */
+#ifdef TGETENT_BROKEN
+# define TGETENT_SUCCESS 0
+#else
+# define TGETENT_SUCCESS 1
+#endif
+#ifdef TGETFLAG_BROKEN
+# define TGETFLAG_SUCCESS 0
+#else
+# define TGETFLAG_SUCCESS 1
+#endif
+#define TGETFLAG(cap) (tgetflag (cap) == TGETFLAG_SUCCESS)
+
static void bind_termcap_arrow_keys PARAMS((Keymap));
/* Variables that hold the screen dimensions, used by the display code. */
@@ -410,6 +427,8 @@ static const struct _tc_string tc_strings[] =
{ "mo", &_rl_term_mo },
{ "nd", &_rl_term_forward_char },
{ "pc", &_rl_term_pc },
+ { "se", &_rl_term_se },
+ { "so", &_rl_term_so },
{ "up", &_rl_term_up },
{ "vb", &_rl_visible_bell },
{ "vs", &_rl_term_vs },
@@ -437,7 +456,7 @@ _rl_init_terminal_io (const char *terminal_name)
{
const char *term;
char *buffer;
- int tty, tgetent_ret;
+ int tty, tgetent_ret, dumbterm;
term = terminal_name ? terminal_name : sh_get_env_value ("TERM");
_rl_term_clrpag = _rl_term_cr = _rl_term_clreol = _rl_term_clrscroll = (char *)NULL;
@@ -446,6 +465,8 @@ _rl_init_terminal_io (const char *terminal_name)
if (term == 0)
term = "dumb";
+ dumbterm = STREQ (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;
@@ -457,6 +478,7 @@ _rl_init_terminal_io (const char *terminal_name)
_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;
+ _rl_term_so = _rl_term_se = (char *)NULL;
#if defined(HACK_TERMCAP_MOTION)
_rl_term_forward_char = (char *)NULL;
#endif
@@ -483,7 +505,7 @@ _rl_init_terminal_io (const char *terminal_name)
tgetent_ret = tgetent (term_buffer, term);
}
- if (tgetent_ret <= 0)
+ if (tgetent_ret != TGETENT_SUCCESS)
{
FREE (term_string_buffer);
FREE (term_buffer);
@@ -521,8 +543,13 @@ _rl_init_terminal_io (const char *terminal_name)
_rl_term_mm = _rl_term_mo = (char *)NULL;
_rl_term_ve = _rl_term_vs = (char *)NULL;
_rl_term_forward_char = (char *)NULL;
+ _rl_term_so = _rl_term_se = (char *)NULL;
_rl_terminal_can_insert = term_has_meta = 0;
+ /* Assume generic unknown terminal can't handle the enable/disable
+ escape sequences */
+ _rl_enable_bracketed_paste = 0;
+
/* Reasonable defaults for tgoto(). Readline currently only uses
tgoto if _rl_term_IC or _rl_term_DC is defined, but just in case we
change that later... */
@@ -541,10 +568,10 @@ _rl_init_terminal_io (const char *terminal_name)
BC = _rl_term_backspace;
UP = _rl_term_up;
- if (!_rl_term_cr)
+ if (_rl_term_cr == 0)
_rl_term_cr = "\r";
- _rl_term_autowrap = tgetflag ("am") && tgetflag ("xn");
+ _rl_term_autowrap = TGETFLAG ("am") && TGETFLAG ("xn");
/* Allow calling application to set default height and width, using
rl_set_screen_size */
@@ -559,7 +586,7 @@ _rl_init_terminal_io (const char *terminal_name)
/* Check to see if this terminal has a meta key and clear the capability
variables if there is none. */
- term_has_meta = tgetflag ("km") != 0;
+ term_has_meta = TGETFLAG ("km");
if (term_has_meta == 0)
_rl_term_mm = _rl_term_mo = (char *)NULL;
#endif /* !__MSDOS__ */
@@ -574,6 +601,11 @@ _rl_init_terminal_io (const char *terminal_name)
bind_termcap_arrow_keys (vi_insertion_keymap);
#endif /* VI_MODE */
+ /* There's no way to determine whether or not a given terminal supports
+ bracketed paste mode, so we assume a terminal named "dumb" does not. */
+ if (dumbterm)
+ _rl_enable_bracketed_paste = 0;
+
return 0;
}
@@ -676,6 +708,16 @@ rl_crlf (void)
return 0;
}
+void
+_rl_cr (void)
+{
+#if defined (__MSDOS__)
+ putc ('\r', rl_outstream);
+#else
+ tputs (_rl_term_cr, 1, _rl_output_character_function);
+#endif
+}
+
/* Ring the terminal bell. */
int
rl_ding (void)
@@ -710,6 +752,30 @@ rl_ding (void)
/* **************************************************************** */
/* */
+/* Entering and leaving terminal standout mode */
+/* */
+/* **************************************************************** */
+
+void
+_rl_standout_on (void)
+{
+#ifndef __MSDOS__
+ if (_rl_term_so && _rl_term_se)
+ tputs (_rl_term_so, 1, _rl_output_character_function);
+#endif
+}
+
+void
+_rl_standout_off (void)
+{
+#ifndef __MSDOS__
+ if (_rl_term_so && _rl_term_se)
+ tputs (_rl_term_se, 1, _rl_output_character_function);
+#endif
+}
+
+/* **************************************************************** */
+/* */
/* Controlling the Meta Key and Keypad */
/* */
/* **************************************************************** */
diff --git a/lib/readline/text.c b/lib/readline/text.c
index cddaeebd..2567dea2 100644
--- a/lib/readline/text.c
+++ b/lib/readline/text.c
@@ -1,6 +1,6 @@
/* text.c -- text handling commands for readline. */
-/* Copyright (C) 1987-2017 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2020 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.
@@ -154,6 +154,7 @@ rl_delete_text (int from, int to)
rl_end -= diff;
rl_line_buffer[rl_end] = '\0';
+ _rl_fix_mark ();
return (diff);
}
@@ -176,6 +177,12 @@ _rl_fix_point (int fix_mark_too)
if (fix_mark_too)
_RL_FIX_POINT (rl_mark);
}
+
+void
+_rl_fix_mark (void)
+{
+ _RL_FIX_POINT (rl_mark);
+}
#undef _RL_FIX_POINT
/* Replace the contents of the line buffer between START and END with
@@ -479,6 +486,8 @@ rl_forward_word (int count, int key)
while (count)
{
+ if (rl_point > rl_end)
+ rl_point = rl_end;
if (rl_point == rl_end)
return 0;
@@ -498,6 +507,8 @@ rl_forward_word (int count, int key)
}
}
+ if (rl_point > rl_end)
+ rl_point = rl_end;
if (rl_point == rl_end)
return 0;
@@ -569,18 +580,8 @@ rl_backward_word (int count, int key)
int
rl_refresh_line (int ignore1, int ignore2)
{
- int curr_line;
-
- curr_line = _rl_current_display_line ();
-
- _rl_move_vert (curr_line);
- _rl_move_cursor_relative (0, rl_line_buffer); /* XXX is this right */
-
- _rl_clear_to_eol (0); /* arg of 0 means to not use spaces */
-
- rl_redraw_prompt_last_line ();
+ _rl_refresh_line ();
rl_display_fixed = 1;
-
return 0;
}
@@ -596,7 +597,18 @@ rl_clear_screen (int count, int key)
return 0;
}
- _rl_clear_screen (); /* calls termcap function to clear screen */
+ _rl_clear_screen (0); /* calls termcap function to clear screen */
+ rl_keep_mark_active ();
+ rl_forced_update_display ();
+ rl_display_fixed = 1;
+
+ return 0;
+}
+
+int
+rl_clear_display (int count, int key)
+{
+ _rl_clear_screen (1); /* calls termcap function to clear screen and scrollback buffer */
rl_forced_update_display ();
rl_display_fixed = 1;
@@ -1080,6 +1092,13 @@ rl_tab_insert (int count, int key)
int
rl_newline (int count, int key)
{
+ if (rl_mark_active_p ())
+ {
+ rl_deactivate_mark ();
+ (*rl_redisplay_function) ();
+ _rl_want_redisplay = 0;
+ }
+
rl_done = 1;
if (_rl_history_preserve_point)
@@ -1452,7 +1471,18 @@ rl_change_case (int count, int op)
if (nwc != wc) /* just skip unchanged characters */
{
char *s, *e;
- mlen = wcrtomb (mb, nwc, &mps);
+ mbstate_t ts;
+
+ memset (&ts, 0, sizeof (mbstate_t));
+ mlen = wcrtomb (mb, nwc, &ts);
+ if (mlen < 0)
+ {
+ nwc = wc;
+ memset (&ts, 0, sizeof (mbstate_t));
+ mlen = wcrtomb (mb, nwc, &ts);
+ if (mlen < 0) /* should not happen */
+ strncpy (mb, rl_line_buffer + start, mlen = m);
+ }
if (mlen > 0)
mb[mlen] = '\0';
/* what to do if m != mlen? adjust below */
@@ -1472,7 +1502,9 @@ rl_change_case (int count, int op)
}
else if (m < mlen)
{
- rl_extend_line_buffer (mlen - m + 1);
+ rl_extend_line_buffer (rl_end + mlen + (e - s) - m + 2);
+ s = rl_line_buffer + start; /* have to redo this */
+ e = rl_line_buffer + rl_end;
memmove (s + mlen, s + m, (e - s) - m);
memcpy (s, mb, mlen);
next += mlen - m; /* next char changes */
@@ -1711,10 +1743,7 @@ _rl_char_search (int count, int fdir, int bdir)
{
int c;
- RL_SETSTATE(RL_STATE_MOREINPUT);
- c = rl_read_key ();
- RL_UNSETSTATE(RL_STATE_MOREINPUT);
-
+ c = _rl_bracketed_read_key ();
if (c < 0)
return 1;
@@ -1809,7 +1838,43 @@ rl_exchange_point_and_mark (int count, int key)
return 1;
}
else
- SWAP (rl_point, rl_mark);
+ {
+ SWAP (rl_point, rl_mark);
+ rl_activate_mark ();
+ }
return 0;
}
+
+/* Active mark support */
+
+/* Is the region active? */
+static int mark_active = 0;
+
+/* Does the current command want the mark to remain active when it completes? */
+int _rl_keep_mark_active;
+
+void
+rl_keep_mark_active (void)
+{
+ _rl_keep_mark_active++;
+}
+
+void
+rl_activate_mark (void)
+{
+ mark_active = 1;
+ rl_keep_mark_active ();
+}
+
+void
+rl_deactivate_mark (void)
+{
+ mark_active = 0;
+}
+
+int
+rl_mark_active_p (void)
+{
+ return (mark_active);
+}
diff --git a/lib/readline/tilde.c b/lib/readline/tilde.c
index 9d0f2961..d678a31a 100644
--- a/lib/readline/tilde.c
+++ b/lib/readline/tilde.c
@@ -1,6 +1,6 @@
/* tilde.c -- Tilde expansion code (~/foo := $HOME/foo). */
-/* Copyright (C) 1988-2017 Free Software Foundation, Inc.
+/* Copyright (C) 1988-2020 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.
@@ -57,10 +57,10 @@ static void *xmalloc (), *xrealloc ();
#if !defined (HAVE_GETPW_DECLS)
# if defined (HAVE_GETPWUID)
-extern struct passwd *getpwuid PARAMS((uid_t));
+extern struct passwd *getpwuid (uid_t);
# endif
# if defined (HAVE_GETPWNAM)
-extern struct passwd *getpwnam PARAMS((const char *));
+extern struct passwd *getpwnam (const char *);
# endif
#endif /* !HAVE_GETPW_DECLS */
@@ -79,8 +79,8 @@ extern struct passwd *getpwnam PARAMS((const char *));
/* If being compiled as part of bash, these will be satisfied from
variables.o. If being compiled as part of readline, they will
be satisfied from shell.o. */
-extern char *sh_get_home_dir PARAMS((void));
-extern char *sh_get_env_value PARAMS((const char *));
+extern char *sh_get_home_dir (void);
+extern char *sh_get_env_value (const char *);
/* The default value of tilde_additional_prefixes. This is set to
whitespace preceding a tilde so that simple programs which do not
@@ -116,10 +116,10 @@ char **tilde_additional_prefixes = (char **)default_prefixes;
`:' and `=~'. */
char **tilde_additional_suffixes = (char **)default_suffixes;
-static int tilde_find_prefix PARAMS((const char *, int *));
-static int tilde_find_suffix PARAMS((const char *));
-static char *isolate_tilde_prefix PARAMS((const char *, int *));
-static char *glue_prefix_and_suffix PARAMS((char *, const char *, int));
+static int tilde_find_prefix (const char *, int *);
+static int tilde_find_suffix (const char *);
+static char *isolate_tilde_prefix (const char *, int *);
+static char *glue_prefix_and_suffix (char *, const char *, int);
/* Find the start of a tilde expansion in STRING, and return the index of
the tilde which starts the expansion. Place the length of the text
diff --git a/lib/readline/undo.c b/lib/readline/undo.c
index ae65d380..14799911 100644
--- a/lib/readline/undo.c
+++ b/lib/readline/undo.c
@@ -196,6 +196,7 @@ rl_do_undo (void)
/* Undoing deletes means inserting some text. */
case UNDO_DELETE:
rl_point = start;
+ _rl_fix_point (1);
rl_insert_text (rl_undo_list->text);
xfree (rl_undo_list->text);
break;
@@ -204,6 +205,7 @@ rl_do_undo (void)
case UNDO_INSERT:
rl_delete_text (start, end);
rl_point = start;
+ _rl_fix_point (1);
break;
/* Undoing an END means undoing everything 'til we get to a BEGIN. */
diff --git a/lib/readline/util.c b/lib/readline/util.c
index e009b238..1576b55d 100644
--- a/lib/readline/util.c
+++ b/lib/readline/util.c
@@ -102,10 +102,11 @@ _rl_abort_internal (void)
rl_clear_message ();
_rl_reset_argument ();
rl_clear_pending_input ();
+ rl_deactivate_mark ();
- RL_UNSETSTATE (RL_STATE_MACRODEF);
while (rl_executing_macro)
_rl_pop_executing_macro ();
+ _rl_kill_kbd_macro ();
RL_UNSETSTATE (RL_STATE_MULTIKEY); /* XXX */
diff --git a/lib/readline/vi_mode.c b/lib/readline/vi_mode.c
index 836371c9..742341e3 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-2018 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2020 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.
@@ -298,6 +298,11 @@ rl_vi_redo (int count, int c)
if (rl_point > 0)
_rl_vi_backup ();
}
+ else if (_rl_vi_last_command == '.' && _rl_keymap == vi_movement_keymap)
+ {
+ rl_ding ();
+ r = 0;
+ }
else
r = _rl_dispatch (_rl_vi_last_command, _rl_keymap);
@@ -320,9 +325,9 @@ rl_vi_yank_arg (int count, int key)
/* Readline thinks that the first word on a line is the 0th, while vi
thinks the first word on a line is the 1st. Compensate. */
if (rl_explicit_arg)
- rl_yank_nth_arg (count - 1, 0);
+ rl_yank_nth_arg (count - 1, key);
else
- rl_yank_nth_arg ('$', 0);
+ rl_yank_nth_arg ('$', key);
return (0);
}
@@ -837,6 +842,12 @@ _rl_vi_save_replace (void)
start = end - vi_replace_count + 1;
len = vi_replace_count + 1;
+ if (start < 0)
+ {
+ len = end + 1;
+ start = 0;
+ }
+
vi_save_insert_buffer (start, len);
}
@@ -864,8 +875,8 @@ _rl_vi_done_inserting (void)
{
if (_rl_vi_doing_insert)
{
- /* The `C', `s', and `S' commands set this. */
- rl_end_undo_group ();
+ /* The `c', `s', `S', and `R' commands set this. */
+ rl_end_undo_group (); /* for the group in rl_vi_start_inserting */
/* Now, the text between rl_undo_list->next->start and
rl_undo_list->next->end is what was inserted while in insert
mode. It gets copied to VI_INSERT_BUFFER because it depends
@@ -876,7 +887,9 @@ _rl_vi_done_inserting (void)
_rl_vi_save_replace (); /* Half the battle */
else
_rl_vi_save_insert (rl_undo_list->next);
- vi_continued_command = 1;
+ /* sanity check, should always be >= 1 here */
+ if (_rl_undo_group_level > 0)
+ rl_end_undo_group (); /* for the group in the command (change or replace) */
}
else
{
@@ -888,10 +901,12 @@ _rl_vi_done_inserting (void)
/* XXX - Other keys probably need to be checked. */
else if (_rl_vi_last_key_before_insert == 'C')
rl_end_undo_group ();
- while (_rl_undo_group_level > 0)
- rl_end_undo_group ();
- vi_continued_command = 0;
}
+
+ /* Sanity check, make sure all the undo groups are closed before we leave
+ insert mode */
+ while (_rl_undo_group_level > 0)
+ rl_end_undo_group ();
}
int
@@ -1162,6 +1177,7 @@ rl_domove_motion_callback (_rl_vimotion_cxt *m)
/* Append a blank character temporarily so that the motion routines
work right at the end of the line. Original value of rl_end is saved
as m->end. */
+ rl_extend_line_buffer (rl_end + 1);
rl_line_buffer[rl_end++] = ' ';
rl_line_buffer[rl_end] = '\0';
@@ -1193,12 +1209,15 @@ _rl_vi_domove_motion_cleanup (int c, _rl_vimotion_cxt *m)
/* Remove the blank that we added in rl_domove_motion_callback. */
rl_end = m->end;
rl_line_buffer[rl_end] = '\0';
- if (rl_point > rl_end)
- rl_point = rl_end;
+ _rl_fix_point (0);
/* No change in position means the command failed. */
if (rl_mark == rl_point)
{
+ /* 'c' and 'C' enter insert mode after the delete even if the motion
+ didn't delete anything, as long as the motion command is valid. */
+ if (_rl_to_upper (m->key) == 'C' && _rl_vi_motion_command (c))
+ return (vidomove_dispatch (m));
RL_UNSETSTATE (RL_STATE_VIMOTION);
return (-1);
}
@@ -1316,13 +1335,7 @@ rl_domove_read_callback (_rl_vimotion_cxt *m)
static int
rl_vi_domove_getchar (_rl_vimotion_cxt *m)
{
- int c;
-
- RL_SETSTATE(RL_STATE_MOREINPUT);
- c = rl_read_key ();
- RL_UNSETSTATE(RL_STATE_MOREINPUT);
-
- return c;
+ return (_rl_bracketed_read_key ());
}
#if defined (READLINE_CALLBACKS)
@@ -1377,7 +1390,11 @@ rl_vi_delete_to (int count, int key)
{
int c, r;
- _rl_vimvcxt = _rl_mvcxt_alloc (VIM_DELETE, key);
+ if (_rl_vimvcxt)
+ _rl_mvcxt_init (_rl_vimvcxt, VIM_DELETE, key);
+ else
+ _rl_vimvcxt = _rl_mvcxt_alloc (VIM_DELETE, key);
+
_rl_vimvcxt->start = rl_point;
rl_mark = rl_point;
@@ -1465,7 +1482,10 @@ rl_vi_change_to (int count, int key)
{
int c, r;
- _rl_vimvcxt = _rl_mvcxt_alloc (VIM_CHANGE, key);
+ if (_rl_vimvcxt)
+ _rl_mvcxt_init (_rl_vimvcxt, VIM_CHANGE, key);
+ else
+ _rl_vimvcxt = _rl_mvcxt_alloc (VIM_CHANGE, key);
_rl_vimvcxt->start = rl_point;
rl_mark = rl_point;
@@ -1524,6 +1544,8 @@ vi_yank_dispatch (_rl_vimotion_cxt *m)
rl_do_undo ();
rl_point = m->start;
+ _rl_fix_point (1);
+
return (0);
}
@@ -1532,7 +1554,10 @@ rl_vi_yank_to (int count, int key)
{
int c, r;
- _rl_vimvcxt = _rl_mvcxt_alloc (VIM_YANK, key);
+ if (_rl_vimvcxt)
+ _rl_mvcxt_init (_rl_vimvcxt, VIM_YANK, key);
+ else
+ _rl_vimvcxt = _rl_mvcxt_alloc (VIM_YANK, key);
_rl_vimvcxt->start = rl_point;
rl_mark = rl_point;
@@ -2000,21 +2025,7 @@ _rl_vi_change_char (int count, int c, char *mb)
static int
_rl_vi_callback_getchar (char *mb, int mlen)
{
- int c;
-
- RL_SETSTATE(RL_STATE_MOREINPUT);
- c = rl_read_key ();
- RL_UNSETSTATE(RL_STATE_MOREINPUT);
-
- if (c < 0)
- return -1;
-
-#if defined (HANDLE_MULTIBYTE)
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- c = _rl_read_mbstring (c, mb, mlen);
-#endif
-
- return c;
+ return (_rl_bracketed_read_mbstring (mb, mlen));
}
#if defined (READLINE_CALLBACKS)
@@ -2026,10 +2037,11 @@ _rl_vi_callback_change_char (_rl_callback_generic_arg *data)
c = _rl_vi_callback_getchar (mb, MB_LEN_MAX);
#if defined (HANDLE_MULTIBYTE)
- strncpy (_rl_vi_last_replacement, mb, MB_LEN_MAX);
-#else
- _rl_vi_last_replacement[0] = c;
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ strncpy (_rl_vi_last_replacement, mb, MB_LEN_MAX);
+ else
#endif
+ _rl_vi_last_replacement[0] = c;
_rl_vi_last_replacement[MB_LEN_MAX] = '\0'; /* XXX */
if (c < 0)
@@ -2066,10 +2078,11 @@ rl_vi_change_char (int count, int key)
{
c = _rl_vi_callback_getchar (mb, MB_LEN_MAX);
#ifdef HANDLE_MULTIBYTE
- strncpy (_rl_vi_last_replacement, mb, MB_LEN_MAX);
-#else
- _rl_vi_last_replacement[0] = c;
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ strncpy (_rl_vi_last_replacement, mb, MB_LEN_MAX);
+ else
#endif
+ _rl_vi_last_replacement[0] = c;
_rl_vi_last_replacement[MB_LEN_MAX] = '\0'; /* just in case */
}
@@ -2122,7 +2135,7 @@ rl_vi_overstrike_delete (int count, int key)
s = rl_point;
if (rl_do_undo ())
- vi_replace_count--;
+ vi_replace_count--; /* XXX */
if (rl_point == s)
rl_backward_char (1, key);
@@ -2137,6 +2150,67 @@ rl_vi_overstrike_delete (int count, int key)
return (0);
}
+static int
+rl_vi_overstrike_kill_line (int count, int key)
+{
+ int r, end;
+
+ end = rl_end;
+ r = rl_unix_line_discard (count, key);
+ vi_replace_count -= end - rl_end;
+ return r;
+}
+
+static int
+rl_vi_overstrike_kill_word (int count, int key)
+{
+ int r, end;
+
+ end = rl_end;
+ r = rl_vi_unix_word_rubout (count, key);
+ vi_replace_count -= end - rl_end;
+ return r;
+}
+
+static int
+rl_vi_overstrike_yank (int count, int key)
+{
+ int r, end;
+
+ end = rl_end;
+ r = rl_yank (count, key);
+ vi_replace_count += rl_end - end;
+ return r;
+}
+
+/* Read bracketed paste mode pasted text and insert it in overwrite mode */
+static int
+rl_vi_overstrike_bracketed_paste (int count, int key)
+{
+ int r;
+ char *pbuf;
+ size_t pblen;
+
+ pbuf = _rl_bracketed_text (&pblen);
+ if (pblen == 0)
+ {
+ xfree (pbuf);
+ return 0;
+ }
+ r = pblen;
+ while (--r >= 0)
+ _rl_unget_char ((unsigned char)pbuf[r]);
+ xfree (pbuf);
+
+ while (_rl_pushed_input_available ())
+ {
+ key = rl_read_key ();
+ r = rl_vi_overstrike (1, key);
+ }
+
+ return r;
+}
+
int
rl_vi_replace (int count, int key)
{
@@ -2169,6 +2243,21 @@ rl_vi_replace (int count, int key)
vi_insertion_keymap[CTRL ('H')].function == rl_rubout)
vi_replace_map[CTRL ('H')].function = rl_vi_overstrike_delete;
+ /* Same for ^U and unix-line-discard. */
+ if (vi_insertion_keymap[CTRL ('U')].type == ISFUNC &&
+ vi_insertion_keymap[CTRL ('U')].function == rl_unix_line_discard)
+ vi_replace_map[CTRL ('U')].function = rl_vi_overstrike_kill_line;
+
+ /* And for ^W and unix-word-rubout. */
+ if (vi_insertion_keymap[CTRL ('W')].type == ISFUNC &&
+ vi_insertion_keymap[CTRL ('W')].function == rl_vi_unix_word_rubout)
+ vi_replace_map[CTRL ('W')].function = rl_vi_overstrike_kill_word;
+
+ /* And finally for ^Y and yank. */
+ if (vi_insertion_keymap[CTRL ('Y')].type == ISFUNC &&
+ vi_insertion_keymap[CTRL ('Y')].function == rl_yank)
+ vi_replace_map[CTRL ('Y')].function = rl_vi_overstrike_yank;
+
/* Make sure this is the value we need. */
vi_replace_map[ANYOTHERKEY].type = ISFUNC;
vi_replace_map[ANYOTHERKEY].function = (rl_command_func_t *)NULL;
@@ -2176,9 +2265,12 @@ rl_vi_replace (int count, int key)
rl_vi_start_inserting (key, 1, rl_arg_sign);
- _rl_vi_last_key_before_insert = key;
+ _rl_vi_last_key_before_insert = 'R'; /* in case someone rebinds it */
_rl_keymap = vi_replace_map;
+ if (_rl_enable_bracketed_paste)
+ rl_bind_keyseq_if_unbound (BRACK_PASTE_PREF, rl_vi_overstrike_bracketed_paste);
+
return (0);
}
@@ -2268,6 +2360,7 @@ _rl_vi_goto_mark (void)
if (ch == '`')
{
rl_point = rl_mark;
+ _rl_fix_point (1);
return 0;
}
else if (ch < 0 || ch < 'a' || ch > 'z') /* make test against 0 explicit */
@@ -2283,6 +2376,7 @@ _rl_vi_goto_mark (void)
return 1;
}
rl_point = vi_mark_chars[ch];
+ _rl_fix_point (1);
return 0;
}
diff --git a/lib/sh/Makefile.in b/lib/sh/Makefile.in
index 06917ba4..98064de5 100644
--- a/lib/sh/Makefile.in
+++ b/lib/sh/Makefile.in
@@ -2,7 +2,7 @@
# Makefile for the Bash library
#
#
-# Copyright (C) 1998-2010 Free Software Foundation, Inc.
+# Copyright (C) 1998-2020 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
@@ -93,7 +93,7 @@ CSOURCES = clktck.c clock.c getcwd.c getenv.c oslib.c setlinebuf.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 wcsnwidth.c shmbchar.c strdup.c \
- utf8.c
+ utf8.c random.c gettimeofday.c
# The header files for this library.
HSOURCES =
@@ -108,7 +108,7 @@ OBJECTS = clktck.o clock.o getenv.o oslib.o setlinebuf.o strnlen.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 \
- utf8.o wcsnwidth.o ${LIBOBJS}
+ utf8.o random.o gettimeofday.o wcsnwidth.o ${LIBOBJS}
SUPPORT = Makefile
@@ -155,6 +155,7 @@ fnxform.o: fnxform.c
fpurge.o: fpurge.c
getcwd.o: getcwd.c
getenv.o: getenv.c
+gettimeofday.o: gettimeofday.c
inet_aton.o: inet_aton.c
input_avail.o: input_avail.c
itos.o: itos.c
@@ -170,6 +171,7 @@ netopen.o: netopen.c
oslib.o: oslib.c
pathcanon.o: pathcanon.c
pathphys.o: pathphys.c
+random.o: random.c
rename.o: rename.c
setlinebuf.o: setlinebuf.c
shmatch.o: shmatch.c
@@ -233,6 +235,7 @@ fnxform.o: ${BUILD_DIR}/config.h
fpurge.o: ${BUILD_DIR}/config.h
getcwd.o: ${BUILD_DIR}/config.h
getenv.o: ${BUILD_DIR}/config.h
+gettimeofday.o: ${BUILD_DIR}/config.h
inet_aton.o: ${BUILD_DIR}/config.h
input_avail.o: ${BUILD_DIR}/config.h
itos.o: ${BUILD_DIR}/config.h
@@ -248,6 +251,7 @@ netopen.o: ${BUILD_DIR}/config.h
oslib.o: ${BUILD_DIR}/config.h
pathcanon.o: ${BUILD_DIR}/config.h
pathphys.o: ${BUILD_DIR}/config.h
+random.o: ${BUILD_DIR}/config.h
rename.o: ${BUILD_DIR}/config.h
setlinebuf.o: ${BUILD_DIR}/config.h
shmatch.o: ${BUILD_DIR}/config.h
@@ -275,7 +279,7 @@ strtoumax.o: ${BUILD_DIR}/config.h
strtrans.o: ${BUILD_DIR}/config.h
times.o: ${BUILD_DIR}/config.h
timeval.o: ${BUILD_DIR}/config.h
-tmpfile.o: ${BUILD_DIR}/config.h
+tmpfile.o: ${BUILD_DIR}/config.h ${topdir}/config-top.h
uconvert.o: ${BUILD_DIR}/config.h
ufuncs.o: ${BUILD_DIR}/config.h
unicode.o: ${BUILD_DIR}/config.h
@@ -380,6 +384,10 @@ pathphys.o: ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/filecntl.h
pathphys.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
#pathphys.o: ${BUILD_DIR}/version.h
+random.o: ${topdir}/bashtypes.h ${BASHINCDIR}/stdc.h
+random.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+random.o: ${BASHINCDIR}/filecntl.h
+
rename.o: ${topdir}/bashtypes.h ${BASHINCDIR}/stdc.h
rename.o: ${BASHINCDIR}/posixstat.h
@@ -505,6 +513,7 @@ times.o: ${BASHINCDIR}/systimes.h
times.o: ${BASHINCDIR}/posixtime.h
timeval.o: ${BASHINCDIR}/posixtime.h
+gettimeofday.o: ${BASHINCDIR}/posixtime.h
tmpfile.o: ${topdir}/bashtypes.h
tmpfile.o: ${BASHINCDIR}/chartypes.h
diff --git a/lib/sh/casemod.c b/lib/sh/casemod.c
index 7cdd4178..bdd96f84 100644
--- a/lib/sh/casemod.c
+++ b/lib/sh/casemod.c
@@ -1,6 +1,6 @@
/* casemod.c -- functions to change case of strings */
-/* Copyright (C) 2008,2009,2015 Free Software Foundation, Inc.
+/* Copyright (C) 2008-2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -67,7 +67,7 @@
#define CASE_USEWORDS 0x1000 /* modify behavior to act on words in passed string */
-extern char *substring __P((char *, int, int));
+extern char *substring PARAMS((char *, int, int));
#ifndef UCHAR_MAX
# define UCHAR_MAX TYPE_MAXIMUM(unsigned char)
diff --git a/lib/sh/eaccess.c b/lib/sh/eaccess.c
index 3d8ae4e8..c3043ec1 100644
--- a/lib/sh/eaccess.c
+++ b/lib/sh/eaccess.c
@@ -1,6 +1,6 @@
/* eaccess.c - eaccess replacement for the shell, plus other access functions. */
-/* Copyright (C) 2006-2010 Free Software Foundation, Inc.
+/* Copyright (C) 2006-2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -52,10 +52,10 @@ extern int errno;
#define F_OK 0
#endif /* R_OK */
-static int path_is_devfd __P((const char *));
-static int sh_stataccess __P((const char *, int));
+static int path_is_devfd PARAMS((const char *));
+static int sh_stataccess PARAMS((const char *, int));
#if HAVE_DECL_SETREGID
-static int sh_euidaccess __P((const char *, int));
+static int sh_euidaccess PARAMS((const char *, int));
#endif
static int
@@ -213,10 +213,10 @@ sh_eaccess (path, mode)
# else /* HAVE_EACCESS */ /* FreeBSD */
ret = eaccess (path, mode); /* XXX -- not always correct for X_OK */
# endif /* HAVE_EACCESS */
-# if defined (__FreeBSD__) || defined (SOLARIS)
+# if defined (__FreeBSD__) || defined (SOLARIS) || defined (_AIX)
if (ret == 0 && current_user.euid == 0 && mode == X_OK)
return (sh_stataccess (path, mode));
-# endif /* __FreeBSD__ || SOLARIS */
+# endif /* __FreeBSD__ || SOLARIS || _AIX */
return ret;
#elif defined (EFF_ONLY_OK) /* SVR4(?), SVR4.2 */
return access (path, mode|EFF_ONLY_OK);
diff --git a/lib/sh/fnxform.c b/lib/sh/fnxform.c
index d7e1b5ad..35d7e737 100644
--- a/lib/sh/fnxform.c
+++ b/lib/sh/fnxform.c
@@ -1,6 +1,6 @@
/* fnxform - use iconv(3) to transform strings to and from "filename" format */
-/* Copyright (C) 2009-2010 Free Software Foundation, Inc.
+/* Copyright (C) 2009-2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -35,9 +35,9 @@
#endif
#if defined (HAVE_LOCALE_CHARSET)
-extern const char *locale_charset __P((void));
+extern const char *locale_charset PARAMS((void));
#else
-extern char *get_locale_var __P((char *));
+extern char *get_locale_var PARAMS((char *));
#endif
#if defined (HAVE_ICONV)
@@ -49,9 +49,9 @@ static iconv_t conv_tofs = (iconv_t)-1;
static char *outbuf = 0;
static size_t outlen = 0;
-static char *curencoding __P((void));
-static void init_tofs __P((void));
-static void init_fromfs __P((void));
+static char *curencoding PARAMS((void));
+static void init_tofs PARAMS((void));
+static void init_fromfs PARAMS((void));
static char *
curencoding ()
diff --git a/lib/sh/fpurge.c b/lib/sh/fpurge.c
index 13e8c78e..8cd4e368 100644
--- a/lib/sh/fpurge.c
+++ b/lib/sh/fpurge.c
@@ -1,6 +1,6 @@
/* fpurge - Flushing buffers of a FILE stream. */
-/* Copyright (C) 2007-2010 Free Software Foundation, Inc.
+/* Copyright (C) 2007-2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -29,7 +29,7 @@
#if HAVE_FPURGE
# define fpurge _bash_fpurge
#endif
-extern int fpurge __P((FILE *stream));
+extern int fpurge PARAMS((FILE *stream));
#if HAVE___FPURGE /* glibc >= 2.2, Haiku, Solaris >= 7 */
# include <stdio_ext.h>
diff --git a/lib/sh/gettimeofday.c b/lib/sh/gettimeofday.c
new file mode 100644
index 00000000..b654c154
--- /dev/null
+++ b/lib/sh/gettimeofday.c
@@ -0,0 +1,35 @@
+/* gettimeofday.c - gettimeofday replacement using time() */
+
+/* Copyright (C) 2020 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 (HAVE_GETTIMEOFDAY)
+
+#include "posixtime.h"
+
+/* A version of gettimeofday that just sets tv_sec from time(3) */
+int
+gettimeofday (struct timeval *tv, void *tz)
+{
+ tv->tv_sec = (time_t) time ((time_t *)0);
+ tv->tv_usec = 0;
+ return 0;
+}
+#endif
diff --git a/lib/sh/input_avail.c b/lib/sh/input_avail.c
index ac157a9f..695165fd 100644
--- a/lib/sh/input_avail.c
+++ b/lib/sh/input_avail.c
@@ -1,7 +1,7 @@
/* input_avail.c -- check whether or not data is available for reading on a
specified file descriptor. */
-/* Copyright (C) 2008,2009 Free Software Foundation, Inc.
+/* Copyright (C) 2008,2009-2019 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -33,6 +33,10 @@
# include <sys/file.h>
#endif /* HAVE_SYS_FILE_H */
+#if defined (HAVE_PSELECT)
+# include <signal.h>
+#endif
+
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif /* HAVE_UNISTD_H */
@@ -82,10 +86,8 @@ input_avail (fd)
timeout.tv_usec = 0;
result = select (fd + 1, &readfds, (fd_set *)NULL, &exceptfds, &timeout);
return ((result <= 0) ? 0 : 1);
-
#endif
- result = -1;
#if defined (FIONREAD)
errno = 0;
result = ioctl (fd, FIONREAD, &chars_avail);
@@ -96,3 +98,68 @@ input_avail (fd)
return 0;
}
+
+/* Wait until NCHARS are available for reading on file descriptor FD.
+ This can wait indefinitely. Return -1 on error. */
+int
+nchars_avail (fd, nchars)
+ int fd;
+ int nchars;
+{
+ int result, chars_avail;
+#if defined(HAVE_SELECT)
+ fd_set readfds, exceptfds;
+#endif
+#if defined (HAVE_PSELECT)
+ sigset_t set, oset;
+#endif
+
+ if (fd < 0 || nchars < 0)
+ return -1;
+ if (nchars == 0)
+ return (input_avail (fd));
+
+ chars_avail = 0;
+
+#if defined (HAVE_SELECT)
+ FD_ZERO (&readfds);
+ FD_ZERO (&exceptfds);
+ FD_SET (fd, &readfds);
+ FD_SET (fd, &exceptfds);
+#endif
+#if defined (HAVE_SELECT) || defined (HAVE_PSELECT)
+ sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &set);
+# ifdef SIGCHLD
+ sigaddset (&set, SIGCHLD);
+# endif
+ sigemptyset (&oset);
+#endif
+
+ while (1)
+ {
+ result = 0;
+#if defined (HAVE_PSELECT)
+ /* XXX - use pselect(2) to block SIGCHLD atomically */
+ result = pselect (fd + 1, &readfds, (fd_set *)NULL, &exceptfds, (struct timespec *)NULL, &set);
+#elif defined (HAVE_SELECT)
+ sigprocmask (SIG_BLOCK, &set, &oset);
+ result = select (fd + 1, &readfds, (fd_set *)NULL, &exceptfds, (struct timeval *)NULL);
+ sigprocmask (SIG_BLOCK, &oset, (sigset_t *)NULL);
+#endif
+ if (result < 0)
+ return -1;
+
+#if defined (FIONREAD)
+ errno = 0;
+ result = ioctl (fd, FIONREAD, &chars_avail);
+ if (result == -1 && errno == EIO)
+ return -1;
+ if (chars_avail >= nchars)
+ break;
+#else
+ break;
+#endif
+ }
+
+ return 0;
+}
diff --git a/lib/sh/mailstat.c b/lib/sh/mailstat.c
index 79b431ae..bd5c25fb 100644
--- a/lib/sh/mailstat.c
+++ b/lib/sh/mailstat.c
@@ -60,7 +60,7 @@ mailstat(path, st)
struct stat st_ret, st_tmp;
DIR *dd;
struct dirent *fn;
- char dir[PATH_MAX * 2], file[PATH_MAX * 2];
+ char dir[PATH_MAX * 2], file[PATH_MAX * 2 + 1];
int i, l;
time_t atime, mtime;
diff --git a/lib/sh/makepath.c b/lib/sh/makepath.c
index ef01718b..ab46c967 100644
--- a/lib/sh/makepath.c
+++ b/lib/sh/makepath.c
@@ -1,6 +1,6 @@
/* makepath.c - glue PATH and DIR together into a full pathname. */
-/* Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -45,7 +45,7 @@
# define MP_IGNDOT 0x08
#endif
-extern char *get_working_directory __P((char *));
+extern char *get_working_directory PARAMS((char *));
static char *nullpath = "";
diff --git a/lib/sh/mktime.c b/lib/sh/mktime.c
index b2b0d3f2..9ee675be 100644
--- a/lib/sh/mktime.c
+++ b/lib/sh/mktime.c
@@ -1,6 +1,6 @@
/* mktime - convert struct tm to a time_t value */
-/* Copyright (C) 1993-2002 Free Software Foundation, Inc.
+/* Copyright (C) 1993-2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Contributed by Paul Eggert (eggert@twinsun.com).
@@ -56,13 +56,13 @@
#define mktime my_mktime
#endif /* DEBUG_MKTIME */
-#ifndef __P
+#ifndef PARAMS
#if defined (__GNUC__) || (defined (__STDC__) && __STDC__)
-#define __P(args) args
+#define PARAMS(args) args
#else
-#define __P(args) ()
+#define PARAMS(args) ()
#endif /* GCC. */
-#endif /* Not __P. */
+#endif /* Not PARAMS. */
#ifndef CHAR_BIT
#define CHAR_BIT 8
@@ -117,13 +117,13 @@ const unsigned short int __mon_yday[2][13] =
{ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
};
-static time_t ydhms_tm_diff __P ((int, int, int, int, int, const struct tm *));
-time_t __mktime_internal __P ((struct tm *,
+static time_t ydhms_tm_diff PARAMS ((int, int, int, int, int, const struct tm *));
+time_t __mktime_internal PARAMS ((struct tm *,
struct tm *(*) (const time_t *, struct tm *),
time_t *));
-static struct tm *my_localtime_r __P ((const time_t *, struct tm *));
+static struct tm *my_localtime_r PARAMS ((const time_t *, struct tm *));
static struct tm *
my_localtime_r (t, tp)
const time_t *t;
@@ -193,7 +193,7 @@ mktime (tp)
time_t
__mktime_internal (tp, convert, offset)
struct tm *tp;
- struct tm *(*convert) __P ((const time_t *, struct tm *));
+ struct tm *(*convert) PARAMS ((const time_t *, struct tm *));
time_t *offset;
{
time_t t, dt, t0;
diff --git a/lib/sh/netopen.c b/lib/sh/netopen.c
index bc3d8f8a..ee0baf66 100644
--- a/lib/sh/netopen.c
+++ b/lib/sh/netopen.c
@@ -5,7 +5,7 @@
* chet@ins.CWRU.Edu
*/
-/* Copyright (C) 1987-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -63,18 +63,18 @@ extern int errno;
#endif
#if !defined (HAVE_INET_ATON)
-extern int inet_aton __P((const char *, struct in_addr *));
+extern int inet_aton PARAMS((const char *, struct in_addr *));
#endif
#ifndef HAVE_GETADDRINFO
-static int _getaddr __P((char *, struct in_addr *));
-static int _getserv __P((char *, int, unsigned short *));
-static int _netopen4 __P((char *, char *, int));
+static int _getaddr PARAMS((char *, struct in_addr *));
+static int _getserv PARAMS((char *, int, unsigned short *));
+static int _netopen4 PARAMS((char *, char *, int));
#else /* HAVE_GETADDRINFO */
-static int _netopen6 __P((char *, char *, int));
+static int _netopen6 PARAMS((char *, char *, int));
#endif
-static int _netopen __P((char *, char *, int));
+static int _netopen PARAMS((char *, char *, int));
#ifndef HAVE_GETADDRINFO
/* Stuff the internet address corresponding to HOST into AP, in network
diff --git a/lib/sh/pathcanon.c b/lib/sh/pathcanon.c
index f9506dff..7d0df9f9 100644
--- a/lib/sh/pathcanon.c
+++ b/lib/sh/pathcanon.c
@@ -90,7 +90,7 @@ _path_isdir (path)
/* Canonicalize PATH, and return a new path. The new path differs from PATH
in that:
- Multple `/'s are collapsed to a single `/'.
+ Multiple `/'s are collapsed to a single `/'.
Leading `./'s and trailing `/.'s are removed.
Trailing `/'s are removed.
Non-leading `../'s and trailing `..'s are handled by removing
diff --git a/lib/sh/pathphys.c b/lib/sh/pathphys.c
index 99390cef..95b72f19 100644
--- a/lib/sh/pathphys.c
+++ b/lib/sh/pathphys.c
@@ -1,6 +1,6 @@
/* pathphys.c -- return pathname with all symlinks expanded. */
-/* Copyright (C) 2000 Free Software Foundation, Inc.
+/* Copyright (C) 2000-2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -46,7 +46,7 @@
extern int errno;
#endif /* !errno */
-extern char *get_working_directory __P((char *));
+extern char *get_working_directory PARAMS((char *));
static int
_path_readlink (path, buf, bufsiz)
diff --git a/lib/sh/random.c b/lib/sh/random.c
new file mode 100644
index 00000000..1eaa71aa
--- /dev/null
+++ b/lib/sh/random.c
@@ -0,0 +1,240 @@
+/* random.c -- Functions for managing 16-bit and 32-bit random numbers. */
+
+/* Copyright (C) 2020 Free Software Foundation, Inc.
+
+ This file is part of GNU Bash, the Bourne Again SHell.
+
+ Bash is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Bash is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Bash. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "config.h"
+
+#include "bashtypes.h"
+
+#if defined (HAVE_SYS_RANDOM_H)
+# include <sys/random.h>
+#endif
+
+#if defined (HAVE_UNISTD_H)
+# include <unistd.h>
+#endif
+#include "filecntl.h"
+
+#include <stdio.h>
+#include "bashansi.h"
+
+#include "shell.h"
+
+extern time_t shell_start_time;
+
+extern int last_random_value;
+
+static u_bits32_t intrand32 PARAMS((u_bits32_t));
+static u_bits32_t genseed PARAMS((void));
+
+static u_bits32_t brand32 PARAMS((void));
+static void sbrand32 PARAMS((u_bits32_t));
+static void perturb_rand32 PARAMS((void));
+
+/* The random number seed. You can change this by setting RANDOM. */
+static u_bits32_t rseed = 1;
+
+/* Returns a 32-bit pseudo-random number. */
+static u_bits32_t
+intrand32 (last)
+ u_bits32_t last;
+{
+ /* Minimal Standard generator from
+ "Random number generators: good ones are hard to find",
+ Park and Miller, Communications of the ACM, vol. 31, no. 10,
+ October 1988, p. 1195. Filtered through FreeBSD.
+
+ x(n+1) = 16807 * x(n) mod (m).
+
+ We split up the calculations to avoid overflow.
+
+ h = last / q; l = x - h * q; t = a * l - h * r
+ m = 2147483647, a = 16807, q = 127773, r = 2836
+
+ There are lots of other combinations of constants to use; look at
+ https://www.gnu.org/software/gsl/manual/html_node/Other-random-number-generators.html#Other-random-number-generators */
+
+ bits32_t h, l, t;
+ u_bits32_t ret;
+
+ /* Can't seed with 0. */
+ ret = (last == 0) ? 123459876 : last;
+ h = ret / 127773;
+ l = ret - (127773 * h);
+ t = 16807 * l - 2836 * h;
+ ret = (t < 0) ? t + 0x7fffffff : t;
+
+ return (ret);
+}
+
+static u_bits32_t
+genseed ()
+{
+ struct timeval tv;
+ u_bits32_t iv;
+
+ gettimeofday (&tv, NULL);
+ iv = (u_bits32_t)seedrand; /* let the compiler truncate */
+ iv = tv.tv_sec ^ tv.tv_usec ^ getpid () ^ getppid () ^ current_user.uid ^ iv;
+ return (iv);
+}
+
+#define BASH_RAND_MAX 32767 /* 0x7fff - 16 bits */
+
+/* Returns a pseudo-random number between 0 and 32767. */
+int
+brand ()
+{
+ unsigned int ret;
+
+ rseed = intrand32 (rseed);
+ if (shell_compatibility_level > 50)
+ ret = (rseed >> 16) ^ (rseed & 65535);
+ else
+ ret = rseed;
+ return (ret & BASH_RAND_MAX);
+}
+
+/* Set the random number generator seed to SEED. */
+void
+sbrand (seed)
+ unsigned long seed;
+{
+ rseed = seed;
+ last_random_value = 0;
+}
+
+void
+seedrand ()
+{
+ u_bits32_t iv;
+
+ iv = genseed ();
+ sbrand (iv);
+}
+
+static u_bits32_t rseed32 = 1073741823;
+static int last_rand32;
+
+static int urandfd = -1;
+
+#define BASH_RAND32_MAX 0x7fffffff /* 32 bits */
+
+/* Returns a 32-bit pseudo-random number between 0 and 4294967295. */
+static u_bits32_t
+brand32 ()
+{
+ u_bits32_t ret;
+
+ rseed32 = intrand32 (rseed32);
+ return (rseed32 & BASH_RAND32_MAX);
+}
+
+static void
+sbrand32 (seed)
+ u_bits32_t seed;
+{
+ last_rand32 = rseed32 = seed;
+}
+
+void
+seedrand32 ()
+{
+ u_bits32_t iv;
+
+ iv = genseed ();
+ sbrand32 (iv);
+}
+
+static void
+perturb_rand32 ()
+{
+ rseed32 ^= genseed ();
+}
+
+/* Force another attempt to open /dev/urandom on the next call to get_urandom32 */
+void
+urandom_close ()
+{
+ if (urandfd >= 0)
+ close (urandfd);
+ urandfd = -1;
+}
+
+#if !defined (HAVE_GETRANDOM)
+/* Imperfect emulation of getrandom(2). */
+#ifndef GRND_NONBLOCK
+# define GRND_NONBLOCK 1
+# define GRND_RANDOM 2
+#endif
+
+static ssize_t
+getrandom (buf, len, flags)
+ void *buf;
+ size_t len;
+ unsigned int flags;
+{
+ int oflags;
+ ssize_t r;
+ static int urand_unavail = 0;
+
+#if HAVE_GETENTROPY
+ r = getentropy (buf, len);
+ return (r == 0) ? len : -1;
+#endif
+
+ if (urandfd == -1 && urand_unavail == 0)
+ {
+ oflags = O_RDONLY;
+ if (flags & GRND_NONBLOCK)
+ oflags |= O_NONBLOCK;
+ urandfd = open ("/dev/urandom", oflags, 0);
+ if (urandfd >= 0)
+ SET_CLOSE_ON_EXEC (urandfd);
+ else
+ {
+ urand_unavail = 1;
+ return -1;
+ }
+ }
+ if (urandfd >= 0 && (r = read (urandfd, buf, len)) == len)
+ return (r);
+ return -1;
+}
+#endif
+
+u_bits32_t
+get_urandom32 ()
+{
+ u_bits32_t ret;
+
+ if (getrandom ((void *)&ret, sizeof (ret), GRND_NONBLOCK) == sizeof (ret))
+ return (last_rand32 = ret);
+
+#if defined (HAVE_ARC4RANDOM)
+ ret = arc4random ();
+#else
+ if (subshell_environment)
+ perturb_rand32 ();
+ do
+ ret = brand32 ();
+ while (ret == last_rand32);
+#endif
+ return (last_rand32 = ret);
+}
diff --git a/lib/sh/shmatch.c b/lib/sh/shmatch.c
index da05211e..d6e7f904 100644
--- a/lib/sh/shmatch.c
+++ b/lib/sh/shmatch.c
@@ -64,7 +64,7 @@ sh_regmatch (string, pattern, flags)
#endif
rflags = REG_EXTENDED;
- if (glob_ignore_case || match_ignore_case)
+ if (match_ignore_case)
rflags |= REG_ICASE;
#if !defined (ARRAY_VARS)
rflags |= REG_NOSUB;
@@ -107,7 +107,9 @@ sh_regmatch (string, pattern, flags)
}
}
+#if 0
VSETATTR (rematch, att_readonly);
+#endif
free (subexp_str);
free (matches);
diff --git a/lib/sh/shquote.c b/lib/sh/shquote.c
index 97e2bc53..680f84ed 100644
--- a/lib/sh/shquote.c
+++ b/lib/sh/shquote.c
@@ -1,6 +1,6 @@
/* shquote - functions to quote and dequote strings */
-/* Copyright (C) 1999-2015 Free Software Foundation, Inc.
+/* Copyright (C) 1999-2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -36,8 +36,8 @@
#include "shmbchar.h"
#include "shmbutil.h"
-extern char *ansic_quote __P((char *, int, int *));
-extern int ansic_shouldquote __P((const char *));
+extern char *ansic_quote PARAMS((char *, int, int *));
+extern int ansic_shouldquote PARAMS((const char *));
/* Default set of characters that should be backslash-quoted in strings */
static const char bstab[256] =
@@ -136,8 +136,15 @@ sh_double_quote (string)
const char *string;
{
register unsigned char c;
+ int mb_cur_max;
char *result, *r;
- const char *s;
+ size_t slen;
+ const char *s, *send;
+ DECLARE_MBSTATE;
+
+ slen = strlen (string);
+ send = string + slen;
+ mb_cur_max = MB_CUR_MAX;
result = (char *)xmalloc (3 + (2 * strlen (string)));
r = result;
@@ -148,12 +155,19 @@ sh_double_quote (string)
/* Backslash-newline disappears within double quotes, so don't add one. */
if ((sh_syntaxtab[c] & CBSDQUOTE) && c != '\n')
*r++ = '\\';
-#if 0
- /* Assume that the string will not be further expanded. */
- else if (c == CTLESC || c == CTLNUL)
- *r++ = CTLESC; /* could be '\\'? */
+
+#if defined (HANDLE_MULTIBYTE)
+ if ((locale_utf8locale && (c & 0x80)) ||
+ (locale_utf8locale == 0 && mb_cur_max > 1 && is_basic (c) == 0))
+ {
+ COPY_CHAR_P (r, s, send);
+ s--; /* compensate for auto-increment in loop above */
+ continue;
+ }
#endif
+ /* Assume that the string will not be further expanded, so no need to
+ add CTLESC to protect CTLESC or CTLNUL. */
*r++ = c;
}
@@ -171,16 +185,29 @@ sh_mkdoublequoted (s, slen, flags)
int slen, flags;
{
char *r, *ret;
- int rlen;
+ const char *send;
+ int rlen, mb_cur_max;
+ DECLARE_MBSTATE;
+ send = s + slen;
+ mb_cur_max = flags ? MB_CUR_MAX : 1;
rlen = (flags == 0) ? slen + 3 : (2 * slen) + 1;
ret = r = (char *)xmalloc (rlen);
-
+
*r++ = '"';
while (*s)
{
if (flags && *s == '"')
*r++ = '\\';
+
+#if defined (HANDLE_MULTIBYTE)
+ if (flags && ((locale_utf8locale && (*s & 0x80)) ||
+ (locale_utf8locale == 0 && mb_cur_max > 1 && is_basic (*s) == 0)))
+ {
+ COPY_CHAR_P (r, s, send);
+ continue;
+ }
+#endif
*r++ = *s++;
}
*r++ = '"';
@@ -259,7 +286,8 @@ sh_backslash_quote (string, table, flags)
*r++ = c;
continue;
}
- if (mb_cur_max > 1 && is_basic (c) == 0)
+ if ((locale_utf8locale && (c & 0x80)) ||
+ (locale_utf8locale == 0 && mb_cur_max > 1 && is_basic (c) == 0))
{
COPY_CHAR_P (r, s, send);
s--; /* compensate for auto-increment in loop above */
@@ -291,18 +319,35 @@ sh_backslash_quote_for_double_quotes (string)
char *string;
{
unsigned char c;
- char *result, *r, *s;
-
- result = (char *)xmalloc (2 * strlen (string) + 1);
+ char *result, *r, *s, *send;
+ size_t slen;
+ int mb_cur_max;
+ DECLARE_MBSTATE;
+
+ slen = strlen (string);
+ send = string + slen;
+ mb_cur_max = MB_CUR_MAX;
+ result = (char *)xmalloc (2 * slen + 1);
for (r = result, s = string; s && (c = *s); s++)
{
- if (sh_syntaxtab[c] & CBSDQUOTE)
+ /* Backslash-newline disappears within double quotes, so don't add one. */
+ if ((sh_syntaxtab[c] & CBSDQUOTE) && c != '\n')
*r++ = '\\';
- /* I should probably add flags for these to sh_syntaxtab[] */
+ /* I should probably use the CSPECL flag for these in sh_syntaxtab[] */
else if (c == CTLESC || c == CTLNUL)
*r++ = CTLESC; /* could be '\\'? */
+#if defined (HANDLE_MULTIBYTE)
+ if ((locale_utf8locale && (c & 0x80)) ||
+ (locale_utf8locale == 0 && mb_cur_max > 1 && is_basic (c) == 0))
+ {
+ COPY_CHAR_P (r, s, send);
+ s--; /* compensate for auto-increment in loop above */
+ continue;
+ }
+#endif
+
*r++ = c;
}
diff --git a/lib/sh/snprintf.c b/lib/sh/snprintf.c
index 6e5892ee..406a3a50 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,2012 Free Software Foundation, Inc.
+ Copyright (C) 2001-2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -129,8 +129,8 @@
# define FL_ADDBASE 0x02 /* add base# prefix to converted value */
# define FL_HEXUPPER 0x04 /* use uppercase when converting to hex */
# define FL_UNSIGNED 0x08 /* don't add any sign */
-extern char *fmtulong __P((unsigned long int, int, char *, size_t, int));
-extern char *fmtullong __P((unsigned long long int, int, char *, size_t, int));
+extern char *fmtulong PARAMS((unsigned long int, int, char *, size_t, int));
+extern char *fmtullong PARAMS((unsigned long long int, int, char *, size_t, int));
#endif
#ifndef FREE
@@ -271,38 +271,38 @@ struct DATA
/* the floating point stuff */
#ifdef FLOATING_POINT
-static double pow_10 __P((int));
-static int log_10 __P((double));
-static double integral __P((double, double *));
-static char *numtoa __P((double, int, int, char **));
+static double pow_10 PARAMS((int));
+static int log_10 PARAMS((double));
+static double integral PARAMS((double, double *));
+static char *numtoa PARAMS((double, int, int, char **));
#endif
-static void init_data __P((struct DATA *, char *, size_t, const char *, int));
-static void init_conv_flag __P((struct DATA *));
+static void init_data PARAMS((struct DATA *, char *, size_t, const char *, int));
+static void init_conv_flag PARAMS((struct DATA *));
/* for the format */
#ifdef FLOATING_POINT
-static void floating __P((struct DATA *, double));
-static void exponent __P((struct DATA *, double));
+static void floating PARAMS((struct DATA *, double));
+static void exponent PARAMS((struct DATA *, double));
#endif
-static void number __P((struct DATA *, unsigned long, int));
+static void number PARAMS((struct DATA *, unsigned long, int));
#ifdef HAVE_LONG_LONG
-static void lnumber __P((struct DATA *, unsigned long long, int));
+static void lnumber PARAMS((struct DATA *, unsigned long long, int));
#endif
-static void pointer __P((struct DATA *, unsigned long));
-static void strings __P((struct DATA *, char *));
+static void pointer PARAMS((struct DATA *, unsigned long));
+static void strings PARAMS((struct DATA *, char *));
#ifdef FLOATING_POINT
# define FALLBACK_FMTSIZE 32
# define FALLBACK_BASE 4096
# define LFALLBACK_BASE 5120
# ifdef HAVE_LONG_DOUBLE
-static void ldfallback __P((struct DATA *, const char *, const char *, long double));
+static void ldfallback PARAMS((struct DATA *, const char *, const char *, long double));
# endif
-static void dfallback __P((struct DATA *, const char *, const char *, double));
+static void dfallback PARAMS((struct DATA *, const char *, const char *, double));
#endif
-static char *groupnum __P((char *));
+static char *groupnum PARAMS((char *));
#if defined (HAVE_LONG_DOUBLE)
# define LONGDOUBLE long double
@@ -332,9 +332,9 @@ static char *groupnum __P((char *));
#ifdef DRIVER
static void memory_error_and_abort ();
-static void *xmalloc __P((size_t));
-static void *xrealloc __P((void *, size_t));
-static void xfree __P((void *));
+static void *xmalloc PARAMS((size_t));
+static void *xrealloc PARAMS((void *, size_t));
+static void xfree PARAMS((void *));
#else
# include <xmalloc.h>
#endif
diff --git a/lib/sh/spell.c b/lib/sh/spell.c
index da78690c..cdf465b2 100644
--- a/lib/sh/spell.c
+++ b/lib/sh/spell.c
@@ -1,6 +1,6 @@
/* spell.c -- spelling correction for pathnames. */
-/* Copyright (C) 2000 Free Software Foundation, Inc.
+/* Copyright (C) 2000-2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -40,8 +40,8 @@
#include <maxpath.h>
#include <stdc.h>
-static int mindist __P((char *, char *, char *));
-static int spdist __P((char *, char *));
+static int mindist PARAMS((char *, char *, char *));
+static int spdist PARAMS((char *, char *));
/*
* `spname' and its helpers are inspired by the code in "The UNIX
diff --git a/lib/sh/strftime.c b/lib/sh/strftime.c
index 0ababc14..08ccb9a3 100644
--- a/lib/sh/strftime.c
+++ b/lib/sh/strftime.c
@@ -62,6 +62,7 @@
#include <stdio.h>
#include <ctype.h>
#include <time.h>
+#include <errno.h>
#if defined(TM_IN_SYS_TIME)
#include <sys/types.h>
@@ -80,6 +81,10 @@
#undef strchr /* avoid AIX weirdness */
+#if !defined (errno)
+extern int errno;
+#endif
+
#if defined (SHELL)
extern char *get_string_value (const char *);
#endif
@@ -172,7 +177,7 @@ strftime(char *s, size_t maxsize, const char *format, const struct tm *timeptr)
char *start = s;
auto char tbuf[100];
long off;
- int i, w;
+ int i, w, oerrno;
long y;
static short first = 1;
#ifdef POSIX_SEMANTICS
@@ -217,6 +222,8 @@ strftime(char *s, size_t maxsize, const char *format, const struct tm *timeptr)
};
static const char *ampm[] = { "AM", "PM", };
+ oerrno = errno;
+
if (s == NULL || format == NULL || timeptr == NULL || maxsize == 0)
return 0;
@@ -642,7 +649,7 @@ strftime(char *s, size_t maxsize, const char *format, const struct tm *timeptr)
sprintf(tbuf+1, "%02ld%02ld", off/60, off%60);
break;
- case 'Z': /* time zone name or abbrevation */
+ case 'Z': /* time zone name or abbreviation */
#ifdef HAVE_TZNAME
i = (daylight && timeptr->tm_isdst > 0); /* 0 or 1 */
strcpy(tbuf, tzname[i]);
@@ -716,6 +723,8 @@ strftime(char *s, size_t maxsize, const char *format, const struct tm *timeptr)
out:
if (s < endp && *format == '\0') {
*s = '\0';
+ if (s == start)
+ errno = oerrno;
return (s - start);
} else
return 0;
@@ -939,7 +948,7 @@ static char *array[] =
"(%%H) hour (24-hour clock, 00..23) %H",
"(%%I) hour (12-hour clock, 01..12) %I",
"(%%M) minute (00..59) %M",
- "(%%N) Emporer/Era Name %N",
+ "(%%N) Emperor/Era Name %N",
"(%%O) Locale extensions (ignored) %O",
"(%%R) time, 24-hour (%%H:%%M) %R",
"(%%S) second (00..60) %S",
@@ -960,7 +969,7 @@ static char *array[] =
"(%%k) hour, 24-hour clock, blank pad ( 0..23) %k",
"(%%l) hour, 12-hour clock, blank pad ( 0..12) %l",
"(%%m) month (01..12) %m",
- "(%%o) Emporer/Era Year %o",
+ "(%%o) Emperor/Era Year %o",
"(%%p) locale's AM or PM based on 12-hour clock %p",
"(%%r) time, 12-hour (same as %%I:%%M:%%S %%p) %r",
"(%%u) ISO 8601: Weekday as decimal number [1 (Monday) - 7] %u",
diff --git a/lib/sh/stringlist.c b/lib/sh/stringlist.c
index b0c272ae..3f28b631 100644
--- a/lib/sh/stringlist.c
+++ b/lib/sh/stringlist.c
@@ -1,6 +1,6 @@
/* stringlist.c - functions to handle a generic `list of strings' structure */
-/* Copyright (C) 2000-2002 Free Software Foundation, Inc.
+/* Copyright (C) 2000-2019 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -255,7 +255,7 @@ strlist_sort (sl)
{
if (sl == 0 || sl->list_len == 0 || sl->list == 0)
return;
- strvec_sort (sl->list);
+ strvec_sort (sl->list, 0);
}
STRINGLIST *
diff --git a/lib/sh/stringvec.c b/lib/sh/stringvec.c
index 3bb4ab70..86000429 100644
--- a/lib/sh/stringvec.c
+++ b/lib/sh/stringvec.c
@@ -122,7 +122,6 @@ strvec_remove (array, name)
return 0;
}
-#ifdef INCLUDE_UNUSED
/* Find NAME in ARRAY. Return the index of NAME, or -1 if not present.
ARRAY should be NULL terminated. */
int
@@ -137,7 +136,6 @@ strvec_search (array, name)
return (-1);
}
-#endif
/* Allocate and return a new copy of ARRAY and its contents. */
char **
@@ -158,6 +156,28 @@ strvec_copy (array)
return (ret);
}
+/* Comparison routine for use by qsort that conforms to the new Posix
+ requirements (http://austingroupbugs.net/view.php?id=1070).
+
+ Perform a bytewise comparison if *S1 and *S2 collate equally. */
+int
+strvec_posixcmp (s1, s2)
+ register char **s1, **s2;
+{
+ int result;
+
+#if defined (HAVE_STRCOLL)
+ result = strcoll (*s1, *s2);
+ if (result != 0)
+ return result;
+#endif
+
+ if ((result = **s1 - **s2) == 0)
+ result = strcmp (*s1, *s2);
+
+ return (result);
+}
+
/* Comparison routine for use with qsort() on arrays of strings. Uses
strcoll(3) if available, otherwise it uses strcmp(3). */
int
@@ -178,10 +198,14 @@ strvec_strcmp (s1, s2)
/* Sort ARRAY, a null terminated array of pointers to strings. */
void
-strvec_sort (array)
+strvec_sort (array, posix)
char **array;
+ int posix;
{
- qsort (array, strvec_len (array), sizeof (char *), (QSFUNC *)strvec_strcmp);
+ if (posix)
+ qsort (array, strvec_len (array), sizeof (char *), (QSFUNC *)strvec_posixcmp);
+ else
+ qsort (array, strvec_len (array), sizeof (char *), (QSFUNC *)strvec_strcmp);
}
/* Cons up a new array of words. The words are taken from LIST,
diff --git a/lib/sh/strtod.c b/lib/sh/strtod.c
index 851d99b9..55e11540 100644
--- a/lib/sh/strtod.c
+++ b/lib/sh/strtod.c
@@ -49,6 +49,10 @@ extern int errno;
# define HUGE_VAL HUGE
#endif
+#ifndef locale_decpoint
+extern int locale_decpoint PARAMS((void));
+#endif
+
/* Convert NPTR to a double. If ENDPTR is not NULL, a pointer to the
character after the last one used in the number is put in *ENDPTR. */
double
@@ -62,6 +66,7 @@ strtod (nptr, endptr)
/* The number so far. */
double num;
+ int radixchar;
int got_dot; /* Found a decimal point. */
int got_digit; /* Seen any digits. */
@@ -85,6 +90,7 @@ strtod (nptr, endptr)
if (*s == '-' || *s == '+')
++s;
+ radixchar = locale_decpoint ();
num = 0.0;
got_dot = 0;
got_digit = 0;
@@ -113,7 +119,7 @@ strtod (nptr, endptr)
if (got_dot)
--exponent;
}
- else if (!got_dot && *s == '.')
+ else if (!got_dot && *s == radixchar)
/* Record that we have found the decimal point. */
got_dot = 1;
else
diff --git a/lib/sh/strtoimax.c b/lib/sh/strtoimax.c
index a4170f06..676e02ef 100644
--- a/lib/sh/strtoimax.c
+++ b/lib/sh/strtoimax.c
@@ -1,6 +1,6 @@
/* strtoimax - convert string representation of a number into an intmax_t value. */
-/* Copyright 1999-2009 Free Software Foundation, Inc.
+/* Copyright 1999-2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -45,14 +45,14 @@
"this configure-time declaration test was not run"
#endif
#if !HAVE_DECL_STRTOL
-extern long strtol __P((const char *, char **, int));
+extern long strtol PARAMS((const char *, char **, int));
#endif
#ifndef HAVE_DECL_STRTOLL
"this configure-time declaration test was not run"
#endif
#if !HAVE_DECL_STRTOLL && HAVE_LONG_LONG
-extern long long strtoll __P((const char *, char **, int));
+extern long long strtoll PARAMS((const char *, char **, int));
#endif
#ifdef strtoimax
diff --git a/lib/sh/strtoumax.c b/lib/sh/strtoumax.c
index 09423add..0247e57b 100644
--- a/lib/sh/strtoumax.c
+++ b/lib/sh/strtoumax.c
@@ -1,6 +1,6 @@
/* strtoumax - convert string representation of a number into an uintmax_t value. */
-/* Copyright 1999-2009 Free Software Foundation, Inc.
+/* Copyright 1999-2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -45,14 +45,14 @@
"this configure-time declaration test was not run"
#endif
#if !HAVE_DECL_STRTOUL
-extern unsigned long strtoul __P((const char *, char **, int));
+extern unsigned long strtoul PARAMS((const char *, char **, int));
#endif
#ifndef HAVE_DECL_STRTOULL
"this configure-time declaration test was not run"
#endif
#if !HAVE_DECL_STRTOULL && HAVE_UNSIGNED_LONG_LONG
-extern unsigned long long strtoull __P((const char *, char **, int));
+extern unsigned long long strtoull PARAMS((const char *, char **, int));
#endif
#ifdef strtoumax
diff --git a/lib/sh/strtrans.c b/lib/sh/strtrans.c
index 48f255f5..b2b1acca 100644
--- a/lib/sh/strtrans.c
+++ b/lib/sh/strtrans.c
@@ -55,12 +55,18 @@ ansicstr (string, len, flags, sawc, rlen)
int c, temp;
char *ret, *r, *s;
unsigned long v;
+ size_t clen;
+ int b, mb_cur_max;
+#if defined (HANDLE_MULTIBYTE)
+ wchar_t wc;
+#endif
if (string == 0 || *string == '\0')
return ((char *)NULL);
+ mb_cur_max = MB_CUR_MAX;
#if defined (HANDLE_MULTIBYTE)
- temp = 4*len + 1;
+ temp = 4*len + 4;
if (temp < 12)
temp = 12; /* ensure enough for eventual u32cesc */
ret = (char *)xmalloc (temp);
@@ -71,7 +77,21 @@ ansicstr (string, len, flags, sawc, rlen)
{
c = *s++;
if (c != '\\' || *s == '\0')
- *r++ = c;
+ {
+ clen = 1;
+#if defined (HANDLE_MULTIBYTE)
+ if ((locale_utf8locale && (c & 0x80)) ||
+ (locale_utf8locale == 0 && mb_cur_max > 0 && is_basic (c) == 0))
+ {
+ clen = mbrtowc (&wc, s - 1, mb_cur_max, 0);
+ if (MB_INVALIDCH (clen))
+ clen = 1;
+ }
+#endif
+ *r++ = c;
+ for (--clen; clen > 0; clen--)
+ *r++ = *s++;
+ }
else
{
switch (c = *s++)
diff --git a/lib/sh/times.c b/lib/sh/times.c
index 47ddf577..2423078a 100644
--- a/lib/sh/times.c
+++ b/lib/sh/times.c
@@ -1,6 +1,6 @@
/* times.c - times(3) library function */
-/* Copyright (C) 1999 Free Software Foundation, Inc.
+/* Copyright (C) 1999-2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -30,7 +30,7 @@
# include <sys/resource.h>
#endif /* HAVE_SYS_RESOURCE_H && HAVE_GETRUSAGE */
-extern long get_clk_tck __P((void));
+extern long get_clk_tck PARAMS((void));
#define CONVTCK(r) (r.tv_sec * clk_tck + r.tv_usec / (1000000 / clk_tck))
@@ -58,7 +58,7 @@ times(tms)
tms->tms_cutime = CONVTCK(ru.ru_utime);
tms->tms_cstime = CONVTCK(ru.ru_stime);
- if (gettimeofday(&tv, (struct timezone *) 0) < 0)
+ if (gettimeofday(&tv, NULL) < 0)
return ((clock_t)-1);
rv = (clock_t)(CONVTCK(tv));
#else /* !HAVE_GETRUSAGE */
diff --git a/lib/sh/timeval.c b/lib/sh/timeval.c
index c4b61dc8..f2ca7624 100644
--- a/lib/sh/timeval.c
+++ b/lib/sh/timeval.c
@@ -67,6 +67,32 @@ addtimeval (d, t1, t2)
return d;
}
+struct timeval *
+multimeval (d, m)
+ struct timeval *d;
+ int m;
+{
+ time_t t;
+
+ t = d->tv_usec * m;
+ d->tv_sec = d->tv_sec * m + t / 1000000;
+ d->tv_usec = t % 1000000;
+ return d;
+}
+
+struct timeval *
+divtimeval (d, m)
+ struct timeval *d;
+ int m;
+{
+ time_t t;
+
+ t = d->tv_sec;
+ d->tv_sec = t / m;
+ d->tv_usec = (d->tv_usec + 1000000 * (t % m)) / m;
+ return d;
+}
+
/* Do "cpu = ((user + sys) * 10000) / real;" with timevals.
Barely-tested code from Deven T. Corzine <deven@ties.org>. */
int
@@ -149,4 +175,5 @@ print_timeval (fp, tvp)
fprintf (fp, "%ldm%d%c%03ds", minutes, seconds, locale_decpoint (), seconds_fraction);
}
+
#endif /* HAVE_TIMEVAL */
diff --git a/lib/sh/tmpfile.c b/lib/sh/tmpfile.c
index e41e45bd..ef8b067b 100644
--- a/lib/sh/tmpfile.c
+++ b/lib/sh/tmpfile.c
@@ -2,7 +2,7 @@
* tmpfile.c - functions to create and safely open temp files for the shell.
*/
-/* Copyright (C) 2000-2015 Free Software Foundation, Inc.
+/* Copyright (C) 2000-2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -54,8 +54,8 @@ extern int errno;
extern pid_t dollar_dollar_pid;
-static char *get_sys_tmpdir __P((void));
-static char *get_tmpdir __P((int));
+static char *get_sys_tmpdir PARAMS((void));
+static char *get_tmpdir PARAMS((int));
static char *sys_tmpdir = (char *)NULL;
static int ntmpfiles;
@@ -146,9 +146,17 @@ sh_mktmpname (nameroot, flags)
tdlen = strlen (tdir);
lroot = nameroot ? nameroot : DEFAULT_NAMEROOT;
+ if (nameroot == 0)
+ flags &= ~MT_TEMPLATE;
+
+ if ((flags & MT_TEMPLATE) && strlen (nameroot) > PATH_MAX)
+ flags &= ~MT_TEMPLATE;
#ifdef USE_MKTEMP
- sprintf (filename, "%s/%s.XXXXXX", tdir, lroot);
+ if (flags & MT_TEMPLATE)
+ strcpy (filename, nameroot);
+ else
+ sprintf (filename, "%s/%s.XXXXXX", tdir, lroot);
if (mktemp (filename) == 0)
{
free (filename);
@@ -192,9 +200,17 @@ sh_mktmpfd (nameroot, flags, namep)
tdlen = strlen (tdir);
lroot = nameroot ? nameroot : DEFAULT_NAMEROOT;
+ if (nameroot == 0)
+ flags &= ~MT_TEMPLATE;
+
+ if ((flags & MT_TEMPLATE) && strlen (nameroot) > PATH_MAX)
+ flags &= ~MT_TEMPLATE;
#ifdef USE_MKSTEMP
- sprintf (filename, "%s/%s.XXXXXX", tdir, lroot);
+ if (flags & MT_TEMPLATE)
+ strcpy (filename, nameroot);
+ else
+ sprintf (filename, "%s/%s.XXXXXX", tdir, lroot);
fd = mkstemp (filename);
if (fd < 0 || namep == 0)
{
@@ -245,3 +261,51 @@ sh_mktmpfp (nameroot, flags, namep)
close (fd);
return fp;
}
+
+char *
+sh_mktmpdir (nameroot, flags)
+ char *nameroot;
+ int flags;
+{
+ char *filename, *tdir, *lroot, *dirname;
+ int fd, tdlen;
+
+#ifdef USE_MKDTEMP
+ filename = (char *)xmalloc (PATH_MAX + 1);
+ tdir = get_tmpdir (flags);
+ tdlen = strlen (tdir);
+
+ lroot = nameroot ? nameroot : DEFAULT_NAMEROOT;
+ if (nameroot == 0)
+ flags &= ~MT_TEMPLATE;
+
+ if ((flags & MT_TEMPLATE) && strlen (nameroot) > PATH_MAX)
+ flags &= ~MT_TEMPLATE;
+
+ if (flags & MT_TEMPLATE)
+ strcpy (filename, nameroot);
+ else
+ sprintf (filename, "%s/%s.XXXXXX", tdir, lroot);
+ dirname = mkdtemp (filename);
+ if (dirname == 0)
+ {
+ free (filename);
+ filename = NULL;
+ }
+ return dirname;
+#else /* !USE_MKDTEMP */
+ filename = (char *)NULL;
+ do
+ {
+ filename = sh_mktmpname (nameroot, flags);
+ fd = mkdir (filename, 0700);
+ if (fd == 0)
+ break;
+ free (filename);
+ filename = (char *)NULL;
+ }
+ while (fd < 0 && errno == EEXIST);
+
+ return (filename);
+#endif /* !USE_MKDTEMP */
+}
diff --git a/lib/sh/uconvert.c b/lib/sh/uconvert.c
index 3d656df0..457552eb 100644
--- a/lib/sh/uconvert.c
+++ b/lib/sh/uconvert.c
@@ -1,7 +1,7 @@
/* uconvert - convert string representations of decimal numbers into whole
number/fractional value pairs. */
-/* Copyright (C) 2008,2009 Free Software Foundation, Inc.
+/* Copyright (C) 2008,2009,2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -23,16 +23,7 @@
#include "bashtypes.h"
-#if defined (TIME_WITH_SYS_TIME)
-# include <sys/time.h>
-# include <time.h>
-#else
-# if defined (HAVE_SYS_TIME_H)
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
-#endif
+#include "posixtime.h"
#if defined (HAVE_UNISTD_H)
#include <unistd.h>
@@ -50,6 +41,7 @@
do { \
if (ip) *ip = ipart * mult; \
if (up) *up = upart; \
+ if (ep) *ep = p; \
return (x); \
} while (0)
@@ -61,12 +53,14 @@ static int multiplier[7] = { 1, 100000, 10000, 1000, 100, 10, 1 };
/* Take a decimal number int-part[.[micro-part]] and convert it to the whole
and fractional portions. The fractional portion is returned in
millionths (micro); callers are responsible for multiplying appropriately.
+ EP, if non-null, gets the address of the character where conversion stops.
Return 1 if value converted; 0 if invalid integer for either whole or
fractional parts. */
int
-uconvert(s, ip, up)
+uconvert(s, ip, up, ep)
char *s;
long *ip, *up;
+ char **ep;
{
int n, mult;
long ipart, upart;
@@ -102,7 +96,14 @@ uconvert(s, ip, up)
for (n = 0; n < 6 && p[n]; n++)
{
if (DIGIT(p[n]) == 0)
- RETURN(0);
+ {
+ if (ep)
+ {
+ upart *= multiplier[n];
+ p += n; /* To set EP */
+ }
+ RETURN(0);
+ }
upart = (upart * 10) + (p[n] - '0');
}
@@ -112,5 +113,12 @@ uconvert(s, ip, up)
if (n == 6 && p[6] >= '5' && p[6] <= '9')
upart++; /* round up 1 */
+ if (ep)
+ {
+ p += n;
+ while (DIGIT(*p))
+ p++;
+ }
+
RETURN(1);
}
diff --git a/lib/sh/ufuncs.c b/lib/sh/ufuncs.c
index ad9284cc..4dc4853b 100644
--- a/lib/sh/ufuncs.c
+++ b/lib/sh/ufuncs.c
@@ -1,6 +1,6 @@
/* ufuncs - sleep and alarm functions that understand fractional values */
-/* Copyright (C) 2008,2009 Free Software Foundation, Inc.
+/* Copyright (C) 2008,2009-2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -22,16 +22,7 @@
#include "bashtypes.h"
-#if defined (TIME_WITH_SYS_TIME)
-# include <sys/time.h>
-# include <time.h>
-#else
-# if defined (HAVE_SYS_TIME_H)
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
-#endif
+#include "posixtime.h"
#if defined (HAVE_UNISTD_H)
#include <unistd.h>
@@ -130,7 +121,7 @@ fsleep(sec, usec)
#endif
e = errno;
if (r < 0 && errno == EINTR)
- QUIT; /* just signals, no traps */
+ return -1; /* caller will handle */
errno = e;
}
while (r < 0 && errno == EINTR);
diff --git a/lib/sh/unicode.c b/lib/sh/unicode.c
index fe13c4a0..d95d1e25 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-2016 Free Software Foundation, Inc.
+/* Copyright (C) 2010-2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -50,9 +50,9 @@
#endif /* !STREQ */
#if defined (HAVE_LOCALE_CHARSET)
-extern const char *locale_charset __P((void));
+extern const char *locale_charset PARAMS((void));
#else
-extern char *get_locale_var __P((char *));
+extern char *get_locale_var PARAMS((char *));
#endif
extern int locale_utf8locale;
@@ -196,7 +196,7 @@ u32toutf8 (wc, s)
}
else if (wc < 0x080000000)
{
- s[0] = (wc >> 30) | 0xf8;
+ s[0] = (wc >> 30) | 0xfc;
s[1] = ((wc >> 24) & 0x3f) | 0x80;
s[2] = ((wc >> 18) & 0x3f) | 0x80;
s[3] = ((wc >> 12) & 0x3f) | 0x80;
@@ -216,21 +216,21 @@ u32toutf8 (wc, s)
int
u32toutf16 (c, s)
u_bits32_t c;
- unsigned short *s;
+ wchar_t *s;
{
int l;
l = 0;
if (c < 0x0d800 || (c >= 0x0e000 && c <= 0x0ffff))
{
- s[0] = (unsigned short) (c & 0xFFFF);
+ s[0] = (wchar_t) (c & 0xFFFF);
l = 1;
}
else if (c >= 0x10000 && c <= 0x010ffff)
{
c -= 0x010000;
- s[0] = (unsigned short)((c >> 10) + 0xd800);
- s[1] = (unsigned short)((c & 0x3ff) + 0xdc00);
+ s[0] = (wchar_t)((c >> 10) + 0xd800);
+ s[1] = (wchar_t)((c & 0x3ff) + 0xdc00);
l = 2;
}
s[l] = 0;
diff --git a/lib/sh/utf8.c b/lib/sh/utf8.c
index d27fcf54..fed25226 100644
--- a/lib/sh/utf8.c
+++ b/lib/sh/utf8.c
@@ -76,13 +76,13 @@ utf8_mbsnlen(src, srclen, maxlen)
return (count);
}
-/* Adapted from GNU gnulib */
+/* Adapted from GNU gnulib. Handles UTF-8 characters up to 4 bytes long */
int
utf8_mblen (s, n)
const char *s;
size_t n;
{
- unsigned char c, c1;
+ unsigned char c, c1, c2, c3;
if (s == 0)
return (0); /* no shift states */
@@ -97,25 +97,74 @@ utf8_mblen (s, n)
c1 = (unsigned char)s[1];
if (c < 0xe0)
{
- if (n >= 2 && (s[1] ^ 0x80) < 0x40)
+ if (n == 1)
+ return -2;
+
+ /*
+ * c c1
+ *
+ * U+0080..U+07FF C2..DF 80..BF
+ */
+
+ if (n >= 2 && (c1 ^ 0x80) < 0x40) /* 0x80..0xbf */
return 2;
}
else if (c < 0xf0)
{
- if (n >= 3
- && (s[1] ^ 0x80) < 0x40 && (s[2] ^ 0x80) < 0x40
+ if (n == 1)
+ return -2;
+
+ /*
+ * c c1 c2
+ *
+ * U+0800..U+0FFF E0 A0..BF 80..BF
+ * U+1000..U+CFFF E1..EC 80..BF 80..BF
+ * U+D000..U+D7FF ED 80..9F 80..BF
+ * U+E000..U+FFFF EE..EF 80..BF 80..BF
+ */
+
+ if ((c1 ^ 0x80) < 0x40
&& (c >= 0xe1 || c1 >= 0xa0)
&& (c != 0xed || c1 < 0xa0))
- return 3;
+ {
+ if (n == 2)
+ return -2; /* incomplete */
+
+ c2 = (unsigned char)s[2];
+ if ((c2 ^ 0x80) < 0x40)
+ return 3;
+ }
}
- else if (c < 0xf8)
+ else if (c <= 0xf4)
{
- if (n >= 4
- && (s[1] ^ 0x80) < 0x40 && (s[2] ^ 0x80) < 0x40
- && (s[3] ^ 0x80) < 0x40
+ if (n == 1)
+ return -2;
+
+ /*
+ * c c1 c2 c3
+ *
+ * U+10000..U+3FFFF F0 90..BF 80..BF 80..BF
+ * U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF
+ * U+100000..U+10FFFF F4 80..8F 80..BF 80..BF
+ */
+ if (((c1 ^ 0x80) < 0x40)
&& (c >= 0xf1 || c1 >= 0x90)
&& (c < 0xf4 || (c == 0xf4 && c1 < 0x90)))
- return 4;
+ {
+ if (n == 2)
+ return -2; /* incomplete */
+
+ c2 = (unsigned char)s[2];
+ if ((c2 ^ 0x80) < 0x40)
+ {
+ if (n == 3)
+ return -2;
+
+ c3 = (unsigned char)s[3];
+ if ((c3 ^ 0x80) < 0x40)
+ return 4;
+ }
+ }
}
}
/* invalid or incomplete multibyte character */
diff --git a/lib/sh/winsize.c b/lib/sh/winsize.c
index ab83433a..861c7c89 100644
--- a/lib/sh/winsize.c
+++ b/lib/sh/winsize.c
@@ -1,6 +1,6 @@
/* winsize.c - handle window size changes and information. */
-/* Copyright (C) 2005-2015 Free Software Foundation, Inc.
+/* Copyright (C) 2005-2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -68,9 +68,9 @@ extern int errno;
extern int shell_tty;
#if defined (READLINE)
-extern void rl_set_screen_size __P((int, int));
+extern void rl_set_screen_size PARAMS((int, int));
#endif
-extern void sh_set_lines_and_columns __P((int, int));
+extern void sh_set_lines_and_columns PARAMS((int, int));
void
get_new_window_size (from_sig, rp, cp)
diff --git a/lib/sh/zcatfd.c b/lib/sh/zcatfd.c
index bdbcd910..aa8199fd 100644
--- a/lib/sh/zcatfd.c
+++ b/lib/sh/zcatfd.c
@@ -1,6 +1,6 @@
/* zcatfd - copy contents of file descriptor to another */
-/* Copyright (C) 2002 Free Software Foundation, Inc.
+/* Copyright (C) 2002-2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -34,8 +34,12 @@
extern int errno;
#endif
-extern ssize_t zread __P((int, char *, size_t));
-extern int zwrite __P((int, char *, ssize_t));
+#ifndef ZBUFSIZ
+# define ZBUFSIZ 4096
+#endif
+
+extern ssize_t zread PARAMS((int, char *, size_t));
+extern int zwrite PARAMS((int, char *, ssize_t));
/* Dump contents of file descriptor FD to OFD. FN is the filename for
error messages (not used right now). */
@@ -46,7 +50,7 @@ zcatfd (fd, ofd, fn)
{
ssize_t nr;
int rval;
- char lbuf[128];
+ char lbuf[ZBUFSIZ];
rval = 0;
while (1)
diff --git a/lib/sh/zgetline.c b/lib/sh/zgetline.c
index a686ba3d..8ded1442 100644
--- a/lib/sh/zgetline.c
+++ b/lib/sh/zgetline.c
@@ -1,7 +1,7 @@
/* zgetline - read a line of input from a specified file descriptor and return
a pointer to a newly-allocated buffer containing the data. */
-/* Copyright (C) 2008,2009 Free Software Foundation, Inc.
+/* Copyright (C) 2008-2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -34,13 +34,13 @@
extern int errno;
#endif
-extern ssize_t zread __P((int, char *, size_t));
-extern ssize_t zreadc __P((int, char *));
-extern ssize_t zreadintr __P((int, char *, size_t));
-extern ssize_t zreadcintr __P((int, char *));
+extern ssize_t zread PARAMS((int, char *, size_t));
+extern ssize_t zreadc PARAMS((int, char *));
+extern ssize_t zreadintr PARAMS((int, char *, size_t));
+extern ssize_t zreadcintr PARAMS((int, char *));
-typedef ssize_t breadfunc_t __P((int, char *, size_t));
-typedef ssize_t creadfunc_t __P((int, char *));
+typedef ssize_t breadfunc_t PARAMS((int, char *, size_t));
+typedef ssize_t creadfunc_t PARAMS((int, char *));
/* Initial memory allocation for automatic growing buffer in zreadlinec */
#define GET_LINE_INITIAL_ALLOCATION 16
diff --git a/lib/sh/zmapfd.c b/lib/sh/zmapfd.c
index e7208921..f9e9ed71 100644
--- a/lib/sh/zmapfd.c
+++ b/lib/sh/zmapfd.c
@@ -1,6 +1,6 @@
/* zmapfd - read contents of file descriptor into a newly-allocated buffer */
-/* Copyright (C) 2006 Free Software Foundation, Inc.
+/* Copyright (C) 2006-2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -36,7 +36,11 @@
extern int errno;
#endif
-extern ssize_t zread __P((int, char *, size_t));
+#ifndef ZBUFSIZ
+# define ZBUFSIZ 4096
+#endif
+
+extern ssize_t zread PARAMS((int, char *, size_t));
/* Dump contents of file descriptor FD to *OSTR. FN is the filename for
error messages (not used right now). */
@@ -48,12 +52,12 @@ zmapfd (fd, ostr, fn)
{
ssize_t nr;
int rval;
- char lbuf[128];
+ char lbuf[ZBUFSIZ];
char *result;
int rsize, rind;
rval = 0;
- result = (char *)xmalloc (rsize = 64);
+ result = (char *)xmalloc (rsize = ZBUFSIZ);
rind = 0;
while (1)
@@ -72,7 +76,7 @@ zmapfd (fd, ostr, fn)
return -1;
}
- RESIZE_MALLOCED_BUFFER (result, rind, nr, rsize, 128);
+ RESIZE_MALLOCED_BUFFER (result, rind, nr, rsize, ZBUFSIZ);
memcpy (result+rind, lbuf, nr);
rind += nr;
}
diff --git a/lib/sh/zread.c b/lib/sh/zread.c
index 8b7ecedf..71a06a76 100644
--- a/lib/sh/zread.c
+++ b/lib/sh/zread.c
@@ -1,6 +1,6 @@
/* zread - read data from file descriptor into buffer with retries */
-/* Copyright (C) 1999-2017 Free Software Foundation, Inc.
+/* Copyright (C) 1999-2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -37,6 +37,10 @@ extern int errno;
# define SEEK_CUR 1
#endif
+#ifndef ZBUFSIZ
+# define ZBUFSIZ 4096
+#endif
+
extern int executing_builtin;
extern void check_signals_and_traps (void);
@@ -55,12 +59,17 @@ zread (fd, buf, len)
check_signals (); /* check for signals before a blocking read */
while ((r = read (fd, buf, len)) < 0 && errno == EINTR)
- /* XXX - bash-5.0 */
- /* We check executing_builtin and run traps here for backwards compatibility */
- if (executing_builtin)
- check_signals_and_traps (); /* XXX - should it be check_signals()? */
- else
- check_signals ();
+ {
+ int t;
+ t = errno;
+ /* XXX - bash-5.0 */
+ /* We check executing_builtin and run traps here for backwards compatibility */
+ if (executing_builtin)
+ check_signals_and_traps (); /* XXX - should it be check_signals()? */
+ else
+ check_signals ();
+ errno = t;
+ }
return r;
}
@@ -112,7 +121,7 @@ zreadintr (fd, buf, len)
in read(2). This does some local buffering to avoid many one-character
calls to read(2), like those the `read' builtin performs. */
-static char lbuf[128];
+static char lbuf[ZBUFSIZ];
static size_t lind, lused;
ssize_t
diff --git a/lib/tilde/tilde.c b/lib/tilde/tilde.c
index 9d0f2961..d678a31a 100644
--- a/lib/tilde/tilde.c
+++ b/lib/tilde/tilde.c
@@ -1,6 +1,6 @@
/* tilde.c -- Tilde expansion code (~/foo := $HOME/foo). */
-/* Copyright (C) 1988-2017 Free Software Foundation, Inc.
+/* Copyright (C) 1988-2020 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.
@@ -57,10 +57,10 @@ static void *xmalloc (), *xrealloc ();
#if !defined (HAVE_GETPW_DECLS)
# if defined (HAVE_GETPWUID)
-extern struct passwd *getpwuid PARAMS((uid_t));
+extern struct passwd *getpwuid (uid_t);
# endif
# if defined (HAVE_GETPWNAM)
-extern struct passwd *getpwnam PARAMS((const char *));
+extern struct passwd *getpwnam (const char *);
# endif
#endif /* !HAVE_GETPW_DECLS */
@@ -79,8 +79,8 @@ extern struct passwd *getpwnam PARAMS((const char *));
/* If being compiled as part of bash, these will be satisfied from
variables.o. If being compiled as part of readline, they will
be satisfied from shell.o. */
-extern char *sh_get_home_dir PARAMS((void));
-extern char *sh_get_env_value PARAMS((const char *));
+extern char *sh_get_home_dir (void);
+extern char *sh_get_env_value (const char *);
/* The default value of tilde_additional_prefixes. This is set to
whitespace preceding a tilde so that simple programs which do not
@@ -116,10 +116,10 @@ char **tilde_additional_prefixes = (char **)default_prefixes;
`:' and `=~'. */
char **tilde_additional_suffixes = (char **)default_suffixes;
-static int tilde_find_prefix PARAMS((const char *, int *));
-static int tilde_find_suffix PARAMS((const char *));
-static char *isolate_tilde_prefix PARAMS((const char *, int *));
-static char *glue_prefix_and_suffix PARAMS((char *, const char *, int));
+static int tilde_find_prefix (const char *, int *);
+static int tilde_find_suffix (const char *);
+static char *isolate_tilde_prefix (const char *, int *);
+static char *glue_prefix_and_suffix (char *, const char *, int);
/* Find the start of a tilde expansion in STRING, and return the index of
the tilde which starts the expansion. Place the length of the text