diff options
| author | Chet Ramey <chet.ramey@case.edu> | 2018-05-22 16:51:07 -0400 |
|---|---|---|
| committer | Chet Ramey <chet.ramey@case.edu> | 2018-05-22 16:51:07 -0400 |
| commit | 9a51695bed07d37086c352372ac69d0a30039a6b (patch) | |
| tree | 4d0f57cba0dd1ec7a75aae56e18cfe9997d0b7a7 /lib | |
| parent | 7de27456f6494f5f9c11ea1c19024d0024f31112 (diff) | |
| download | bash-5.0-alpha.tar.gz | |
bash-5.0-alpha releasebash-5.0-alpha
Diffstat (limited to 'lib')
75 files changed, 3088 insertions, 3626 deletions
diff --git a/lib/glob/Makefile.in b/lib/glob/Makefile.in index 23bf8c8b..314622f1 100644 --- a/lib/glob/Makefile.in +++ b/lib/glob/Makefile.in @@ -53,7 +53,7 @@ BASHINCDIR = ${topdir}/include INCLUDES = -I. -I../.. -I$(topdir) -I$(BASHINCDIR) -I$(topdir)/lib CCFLAGS = $(PROFILE_FLAGS) $(DEFS) $(LOCAL_DEFS) ${INCLUDES} $(CPPFLAGS) \ - $(LOCAL_CFLAGS) $(CFLAGS) + $(LOCAL_CFLAGS) $(CFLAGS) ${ADDON_CFLAGS} # Here is a rule for making .o files from .c files that doesn't force # the type of the machine (like -sun3) into the flags. @@ -164,4 +164,5 @@ xmbsrtowcs.o: xmbsrtowcs.c # dependencies for C files that include other C files glob.o: glob_loop.c +gmisc.o: gm_loop.c smatch.o: sm_loop.c diff --git a/lib/glob/glob.c b/lib/glob/glob.c index 7f6eafe7..774435f1 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-2009 Free Software Foundation, Inc. + Copyright (C) 1985-2017 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne-Again SHell. @@ -123,10 +123,14 @@ static char **glob_dir_to_array __P((char *, char **, int)); extern char *glob_patscan __P((char *, char *, int)); extern wchar_t *glob_patscan_wc __P((wchar_t *, wchar_t *, int)); +/* And this from gmisc.c/gm_loop.c */ +extern int wextglob_pattern_p __P((wchar_t *)); + extern char *glob_dirscan __P((char *, int)); /* Compile `glob_loop.c' for single-byte characters. */ -#define CHAR unsigned char +#define GCHAR unsigned char +#define CHAR char #define INT int #define L(CS) CS #define INTERNAL_GLOB_PATTERN_P internal_glob_pattern_p @@ -135,6 +139,7 @@ extern char *glob_dirscan __P((char *, int)); /* Compile `glob_loop.c' again for multibyte characters. */ #if HANDLE_MULTIBYTE +#define GCHAR wchar_t #define CHAR wchar_t #define INT wint_t #define L(CS) L##CS @@ -182,9 +187,10 @@ extglob_skipname (pat, dname, flags) int flags; { char *pp, *pe, *t, *se; - int n, r, negate; + int n, r, negate, wild; negate = *pat == '!'; + wild = *pat == '*' || *pat == '?'; pp = pat + 2; se = pp + strlen (pp) - 1; /* end of string */ pe = glob_patscan (pp, se, 0); /* end of extglob pattern (( */ @@ -203,14 +209,19 @@ extglob_skipname (pat, dname, flags) r = skipname (pp, dname, flags); /*(*/ #endif *pe = ')'; + if (wild && pe[1]) /* if we can match zero instances, check further */ + return (skipname (pe+1, dname, flags)); return r; } /* check every subpattern */ while (t = glob_patscan (pp, pe, '|')) { - n = t[-1]; - t[-1] = '\0'; + n = t[-1]; /* ( */ + if (extglob_pattern_p (pp) && n == ')') + t[-1] = n; /* no-op for now */ + else + t[-1] = '\0'; #if defined (HANDLE_MULTIBYTE) r = mbskipname (pp, dname, flags); #else @@ -222,12 +233,14 @@ extglob_skipname (pat, dname, flags) pp = t; } /*(*/ - /* glob_patscan might find end of pattern */ + /* glob_patscan might find end of string */ if (pp == se) return r; /* but if it doesn't then we didn't match a leading dot */ - return 0; + if (wild && *pe) /* if we can match zero instances, check further */ + return (skipname (pe, dname, flags)); + return 1; } #endif @@ -263,22 +276,23 @@ skipname (pat, dname, flags) #if HANDLE_MULTIBYTE static int -wchkname (pat_wc, dn_wc) - wchar_t *pat_wc, *dn_wc; +wskipname (pat, dname, flags) + wchar_t *pat, *dname; + int flags; { /* If a leading dot need not be explicitly matched, and the pattern doesn't start with a `.', don't match `.' or `..' */ - if (noglob_dot_filenames == 0 && pat_wc[0] != L'.' && - (pat_wc[0] != L'\\' || pat_wc[1] != L'.') && - (dn_wc[0] == L'.' && - (dn_wc[1] == L'\0' || (dn_wc[1] == L'.' && dn_wc[2] == L'\0')))) + 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')))) return 1; /* If a leading dot must be explicitly matched, check to see if the pattern and dirname both have one. */ - else if (noglob_dot_filenames && dn_wc[0] == L'.' && - pat_wc[0] != L'.' && - (pat_wc[0] != L'\\' || pat_wc[1] != L'.')) + else if (noglob_dot_filenames && dname[0] == L'.' && + pat[0] != L'.' && + (pat[0] != L'\\' || pat[1] != L'.')) return 1; return 0; @@ -291,9 +305,10 @@ wextglob_skipname (pat, dname, flags) { #if EXTENDED_GLOB wchar_t *pp, *pe, *t, n, *se; - int r, negate; + int r, negate, wild; negate = *pat == L'!'; + wild = *pat == L'*' || *pat == L'?'; pp = pat + 2; se = pp + wcslen (pp) - 1; /*(*/ pe = glob_patscan_wc (pp, se, 0); @@ -301,17 +316,22 @@ wextglob_skipname (pat, dname, flags) if (pe == se && *pe == ')' && (t = wcschr (pp, L'|')) == 0) { *pe = L'\0'; - r = wchkname (pp, dname); /*(*/ + r = wskipname (pp, dname, flags); /*(*/ *pe = L')'; + if (wild && pe[1] != L'\0') + return (wskipname (pe+1, dname, flags)); return r; } /* check every subpattern */ while (t = glob_patscan_wc (pp, pe, '|')) { - n = t[-1]; - t[-1] = L'\0'; - r = wchkname (pp, dname); + n = t[-1]; /* ( */ + if (wextglob_pattern_p (pp) && n == L')') + t[-1] = n; /* no-op for now */ + else + t[-1] = L'\0'; + r = wskipname (pp, dname, flags); t[-1] = n; if (r == 0) return 0; @@ -322,9 +342,11 @@ wextglob_skipname (pat, dname, flags) return r; /* but if it doesn't then we didn't match a leading dot */ - return 0; + if (wild && *pe != L'\0') + return (wskipname (pe, dname, flags)); + return 1; #else - return (wchkname (pat, dname)); + return (wskipname (pat, dname, flags)); #endif } @@ -355,7 +377,7 @@ mbskipname (pat, dname, flags) ret = 0; if (pat_n != (size_t)-1 && dn_n !=(size_t)-1) - ret = ext ? wextglob_skipname (pat_wc, dn_wc, flags) : wchkname (pat_wc, dn_wc); + ret = ext ? wextglob_skipname (pat_wc, dn_wc, flags) : wskipname (pat_wc, dn_wc, flags); else ret = skipname (pat, dname, flags); @@ -455,7 +477,7 @@ dequote_pathname (pathname) # endif /* AFS */ #endif /* !HAVE_LSTAT */ -/* Return 0 if DIR is a directory, -1 otherwise. */ +/* Return 0 if DIR is a directory, -2 if DIR is a symlink, -1 otherwise. */ static int glob_testdir (dir, flags) char *dir; @@ -473,6 +495,11 @@ glob_testdir (dir, flags) if (r < 0) return (-1); +#if defined (S_ISLNK) + if (S_ISLNK (finfo.st_mode)) + return (-2); +#endif + if (S_ISDIR (finfo.st_mode) == 0) return (-1); @@ -778,6 +805,15 @@ 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) firstmalloc = nextlink; @@ -1018,7 +1054,7 @@ glob_filename (pathname, flags) char *pathname; int flags; { - char **result; + char **result, **new_result; unsigned int result_size; char *directory_name, *filename, *dname, *fn; unsigned int directory_len; @@ -1248,16 +1284,16 @@ glob_filename (pathname, flags) while (array[l] != NULL) ++l; - result = - (char **)realloc (result, (result_size + l) * sizeof (char *)); + new_result = (char **)realloc (result, (result_size + l) * sizeof (char *)); - if (result == NULL) + if (new_result == NULL) { for (l = 0; array[l]; ++l) free (array[l]); free ((char *)array); goto memory_error; } + result = new_result; for (l = 0; array[l] != NULL; ++l) result[result_size++ - 1] = array[l]; diff --git a/lib/glob/glob_loop.c b/lib/glob/glob_loop.c index 89e86af5..7d6ae211 100644 --- a/lib/glob/glob_loop.c +++ b/lib/glob/glob_loop.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2005 Free Software Foundation, Inc. +/* Copyright (C) 1991-2017 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne Again SHell. @@ -16,16 +16,16 @@ along with Bash. If not, see <http://www.gnu.org/licenses/>. */ -static int INTERNAL_GLOB_PATTERN_P __P((const CHAR *)); +static int INTERNAL_GLOB_PATTERN_P __P((const GCHAR *)); /* Return nonzero if PATTERN has any special globbing chars in it. Compiled twice, once each for single-byte and multibyte characters. */ static int INTERNAL_GLOB_PATTERN_P (pattern) - const CHAR *pattern; + const GCHAR *pattern; { - register const CHAR *p; - register CHAR c; + register const GCHAR *p; + register GCHAR c; int bopen; p = pattern; @@ -54,8 +54,11 @@ INTERNAL_GLOB_PATTERN_P (pattern) continue; case L('\\'): - if (*p++ == L('\0')) - return 0; + /* Don't let the pattern end in a backslash (GMATCH returns no match + if the pattern ends in a backslash anyway), but otherwise return 1, + since the matching engine uses backslash as an escape character + and it can be removed. */ + return (*p != L('\0')); } return 0; @@ -65,3 +68,4 @@ INTERNAL_GLOB_PATTERN_P (pattern) #undef L #undef INT #undef CHAR +#undef GCHAR diff --git a/lib/glob/gm_loop.c b/lib/glob/gm_loop.c new file mode 100644 index 00000000..ac516f82 --- /dev/null +++ b/lib/glob/gm_loop.c @@ -0,0 +1,208 @@ +/* Copyright (C) 1991-2017 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/>. +*/ + +#if EXTENDED_GLOB +int +EXTGLOB_PATTERN_P (pat) + const CHAR *pat; +{ + switch (pat[0]) + { + case L('*'): + case L('+'): + case L('!'): + case L('@'): + case L('?'): + return (pat[1] == L('(')); /* ) */ + default: + return 0; + } + + return 0; +} +#endif + +/* Return 1 of the first character of STRING could match the first + character of pattern PAT. Compiled to both single and wiide character + versions. FLAGS is a subset of strmatch flags; used to do case-insensitive + matching for now. */ +int +MATCH_PATTERN_CHAR (pat, string, flags) + CHAR *pat, *string; + int flags; +{ + CHAR c; + + if (*string == 0) + return (*pat == L('*')); /* XXX - allow only * to match empty string */ + + switch (c = *pat++) + { + default: + return (FOLD(*string) == FOLD(c)); + case L('\\'): + return (FOLD(*string) == FOLD(*pat)); + case L('?'): + return (*pat == L('(') ? 1 : (*string != L'\0')); + case L('*'): + return (1); + case L('+'): + case L('!'): + case L('@'): + return (*pat == L('(') ? 1 : (FOLD(*string) == FOLD(c))); + case L('['): + return (*string != L('\0')); + } +} + +int +MATCHLEN (pat, max) + CHAR *pat; + size_t max; +{ + CHAR c; + int matlen, bracklen, t, in_cclass, in_collsym, in_equiv; + + if (*pat == 0) + return (0); + + matlen = in_cclass = in_collsym = in_equiv = 0; + while (c = *pat++) + { + switch (c) + { + default: + matlen++; + break; + case L('\\'): + if (*pat == 0) + return ++matlen; + else + { + matlen++; + pat++; + } + break; + case L('?'): + if (*pat == LPAREN) + return (matlen = -1); /* XXX for now */ + else + matlen++; + break; + case L('*'): + return (matlen = -1); + case L('+'): + case L('!'): + case L('@'): + if (*pat == LPAREN) + return (matlen = -1); /* XXX for now */ + else + matlen++; + break; + case L('['): + /* scan for ending `]', skipping over embedded [:...:] */ + bracklen = 1; + c = *pat++; + do + { + if (c == 0) + { + pat--; /* back up to NUL */ + matlen += bracklen; + goto bad_bracket; + } + else if (c == L('\\')) + { + /* *pat == backslash-escaped character */ + bracklen++; + /* If the backslash or backslash-escape ends the string, + bail. The ++pat skips over the backslash escape */ + if (*pat == 0 || *++pat == 0) + { + matlen += bracklen; + goto bad_bracket; + } + } + else if (c == L('[') && *pat == L(':')) /* character class */ + { + pat++; + bracklen++; + in_cclass = 1; + } + else if (in_cclass && c == L(':') && *pat == L(']')) + { + pat++; + bracklen++; + in_cclass = 0; + } + else if (c == L('[') && *pat == L('.')) /* collating symbol */ + { + pat++; + bracklen++; + if (*pat == L(']')) /* right bracket can appear as collating symbol */ + { + pat++; + bracklen++; + } + in_collsym = 1; + } + else if (in_collsym && c == L('.') && *pat == L(']')) + { + pat++; + bracklen++; + in_collsym = 0; + } + else if (c == L('[') && *pat == L('=')) /* equivalence class */ + { + pat++; + bracklen++; + if (*pat == L(']')) /* right bracket can appear as equivalence class */ + { + pat++; + bracklen++; + } + in_equiv = 1; + } + else if (in_equiv && c == L('=') && *pat == L(']')) + { + pat++; + bracklen++; + in_equiv = 0; + } + else + bracklen++; + } + while ((c = *pat++) != L(']')); + matlen++; /* bracket expression can only match one char */ +bad_bracket: + break; + } + } + + return matlen; +} + +#undef EXTGLOB_PATTERN_P +#undef MATCH_PATTERN_CHAR +#undef MATCHLEN +#undef FOLD +#undef L +#undef LPAREN +#undef RPAREN +#undef INT +#undef CHAR diff --git a/lib/glob/gmisc.c b/lib/glob/gmisc.c index 31906a4f..a2bca965 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 Free Software Foundation, Inc. + Copyright (C) 2010-2017 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne-Again SHell. @@ -35,367 +35,44 @@ #ifndef FNM_CASEFOLD # include "strmatch.h" #endif - -#ifndef LPAREN -# define LPAREN '(' -#endif -#ifndef RPAREN -# define RPAREN ')' -#endif - -#if defined (HANDLE_MULTIBYTE) -#define WLPAREN L'(' -#define WRPAREN L')' +#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 wchar_t *glob_patscan_wc __P((wchar_t *, wchar_t *, int)); - -#define FOLD(c) ((flags & FNM_CASEFOLD) && iswupper (c) ? towlower (c) : (c)) - -/* Return 1 of the first character of WSTRING could match the first - character of pattern WPAT. Wide character version. FLAGS is a - subset of strmatch flags; used to do case-insensitive matching for now. */ -int -match_pattern_wchar (wpat, wstring, flags) - wchar_t *wpat, *wstring; - int flags; -{ - wchar_t wc; - - if (*wstring == 0) - return (*wpat == L'*'); /* XXX - allow only * to match empty string */ - - switch (wc = *wpat++) - { - default: - return (FOLD(*wstring) == FOLD(wc)); - case L'\\': - return (FOLD(*wstring) == FOLD(*wpat)); - case L'?': - return (*wpat == WLPAREN ? 1 : (*wstring != L'\0')); - case L'*': - return (1); - case L'+': - case L'!': - case L'@': - return (*wpat == WLPAREN ? 1 : (FOLD(*wstring) == FOLD(wc))); - case L'[': - return (*wstring != L'\0'); - } -} - -int -wmatchlen (wpat, wmax) - wchar_t *wpat; - size_t wmax; -{ - wchar_t wc; - int matlen, bracklen, t, in_cclass, in_collsym, in_equiv; - - if (*wpat == 0) - return (0); - - matlen = in_cclass = in_collsym = in_equiv = 0; - while (wc = *wpat++) - { - switch (wc) - { - default: - matlen++; - break; - case L'\\': - if (*wpat == 0) - return ++matlen; - else - { - matlen++; - wpat++; - } - break; - case L'?': - if (*wpat == WLPAREN) - return (matlen = -1); /* XXX for now */ - else - matlen++; - break; - case L'*': - return (matlen = -1); - case L'+': - case L'!': - case L'@': - if (*wpat == WLPAREN) - return (matlen = -1); /* XXX for now */ - else - matlen++; - break; - case L'[': - /* scan for ending `]', skipping over embedded [:...:] */ - bracklen = 1; - wc = *wpat++; - do - { - if (wc == 0) - { - wpat--; /* back up to NUL */ - matlen += bracklen; - goto bad_bracket; - } - else if (wc == L'\\') - { - /* *wpat == backslash-escaped character */ - bracklen++; - /* If the backslash or backslash-escape ends the string, - bail. The ++wpat skips over the backslash escape */ - if (*wpat == 0 || *++wpat == 0) - { - matlen += bracklen; - goto bad_bracket; - } - } - else if (wc == L'[' && *wpat == L':') /* character class */ - { - wpat++; - bracklen++; - in_cclass = 1; - } - else if (in_cclass && wc == L':' && *wpat == L']') - { - wpat++; - bracklen++; - in_cclass = 0; - } - else if (wc == L'[' && *wpat == L'.') /* collating symbol */ - { - wpat++; - bracklen++; - if (*wpat == L']') /* right bracket can appear as collating symbol */ - { - wpat++; - bracklen++; - } - in_collsym = 1; - } - else if (in_collsym && wc == L'.' && *wpat == L']') - { - wpat++; - bracklen++; - in_collsym = 0; - } - else if (wc == L'[' && *wpat == L'=') /* equivalence class */ - { - wpat++; - bracklen++; - if (*wpat == L']') /* right bracket can appear as equivalence class */ - { - wpat++; - bracklen++; - } - in_equiv = 1; - } - else if (in_equiv && wc == L'=' && *wpat == L']') - { - wpat++; - bracklen++; - in_equiv = 0; - } - else - bracklen++; - } - while ((wc = *wpat++) != L']'); - matlen++; /* bracket expression can only match one char */ -bad_bracket: - break; - } - } - return matlen; -} -#endif - -int -extglob_pattern_p (pat) - char *pat; -{ - switch (pat[0]) - { - case '*': - case '+': - case '!': - case '@': - case '?': - return (pat[1] == LPAREN); - default: - return 0; - } - - return 0; -} - -#undef FOLD +/* Compile `gm_loop.c' for single-byte characters. */ +#define CHAR char +#define INT int +#define L(CS) CS +#define EXTGLOB_PATTERN_P extglob_pattern_p +#define MATCH_PATTERN_CHAR match_pattern_char +#define MATCHLEN umatchlen #define FOLD(c) ((flags & FNM_CASEFOLD) \ ? TOLOWER ((unsigned char)c) \ : ((unsigned char)c)) +#ifndef LPAREN +#define LPAREN '(' +#define RPAREN ')' +#endif +#include "gm_loop.c" -/* Return 1 of the first character of STRING could match the first - character of pattern PAT. Used to avoid n2 calls to strmatch(). - FLAGS is a subset of strmatch flags; used to do case-insensitive - matching for now. */ -int -match_pattern_char (pat, string, flags) - char *pat, *string; - int flags; -{ - char c; +/* Compile `gm_loop.c' again for multibyte characters. */ +#if HANDLE_MULTIBYTE - if (*string == 0) - return (*pat == '*'); /* XXX - allow only * to match empty string */ +#define CHAR wchar_t +#define INT wint_t +#define L(CS) L##CS +#define EXTGLOB_PATTERN_P wextglob_pattern_p +#define MATCH_PATTERN_CHAR match_pattern_wchar +#define MATCHLEN wmatchlen - switch (c = *pat++) - { - default: - return (FOLD(*string) == FOLD(c)); - case '\\': - return (FOLD(*string) == FOLD(*pat)); - case '?': - return (*pat == LPAREN ? 1 : (*string != '\0')); - case '*': - return (1); - case '+': - case '!': - case '@': - return (*pat == LPAREN ? 1 : (FOLD(*string) == FOLD(c))); - case '[': - return (*string != '\0'); - } -} - -int -umatchlen (pat, max) - char *pat; - size_t max; -{ - char c; - int matlen, bracklen, t, in_cclass, in_collsym, in_equiv; +#define FOLD(c) ((flags & FNM_CASEFOLD) && iswupper (c) ? towlower (c) : (c)) +#define LPAREN L'(' +#define RPAREN L')' +#include "gm_loop.c" - if (*pat == 0) - return (0); +#endif /* HANDLE_MULTIBYTE */ - matlen = in_cclass = in_collsym = in_equiv = 0; - while (c = *pat++) - { - switch (c) - { - default: - matlen++; - break; - case '\\': - if (*pat == 0) - return ++matlen; - else - { - matlen++; - pat++; - } - break; - case '?': - if (*pat == LPAREN) - return (matlen = -1); /* XXX for now */ - else - matlen++; - break; - case '*': - return (matlen = -1); - case '+': - case '!': - case '@': - if (*pat == LPAREN) - return (matlen = -1); /* XXX for now */ - else - matlen++; - break; - case '[': - /* scan for ending `]', skipping over embedded [:...:] */ - bracklen = 1; - c = *pat++; - do - { - if (c == 0) - { - pat--; /* back up to NUL */ - matlen += bracklen; - goto bad_bracket; - } - else if (c == '\\') - { - /* *pat == backslash-escaped character */ - bracklen++; - /* If the backslash or backslash-escape ends the string, - bail. The ++pat skips over the backslash escape */ - if (*pat == 0 || *++pat == 0) - { - matlen += bracklen; - goto bad_bracket; - } - } - else if (c == '[' && *pat == ':') /* character class */ - { - pat++; - bracklen++; - in_cclass = 1; - } - else if (in_cclass && c == ':' && *pat == ']') - { - pat++; - bracklen++; - in_cclass = 0; - } - else if (c == '[' && *pat == '.') /* collating symbol */ - { - pat++; - bracklen++; - if (*pat == ']') /* right bracket can appear as collating symbol */ - { - pat++; - bracklen++; - } - in_collsym = 1; - } - else if (in_collsym && c == '.' && *pat == ']') - { - pat++; - bracklen++; - in_collsym = 0; - } - else if (c == '[' && *pat == '=') /* equivalence class */ - { - pat++; - bracklen++; - if (*pat == ']') /* right bracket can appear as equivalence class */ - { - pat++; - bracklen++; - } - in_equiv = 1; - } - else if (in_equiv && c == '=' && *pat == ']') - { - pat++; - bracklen++; - in_equiv = 0; - } - else - bracklen++; - } - while ((c = *pat++) != ']'); - matlen++; /* bracket expression can only match one char */ -bad_bracket: - break; - } - } - - return matlen; -} #if defined (EXTENDED_GLOB) /* Skip characters in PAT and return the final occurrence of DIRSEP. This diff --git a/lib/glob/sm_loop.c b/lib/glob/sm_loop.c index 65179e24..2de5acd3 100644 --- a/lib/glob/sm_loop.c +++ b/lib/glob/sm_loop.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2011 Free Software Foundation, Inc. +/* Copyright (C) 1991-2018 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne Again SHell. @@ -16,9 +16,15 @@ along with Bash. If not, see <http://www.gnu.org/licenses/>. */ +struct STRUCT +{ + CHAR *pattern; + CHAR *string; +}; + int FCT __P((CHAR *, CHAR *, int)); -static int GMATCH __P((CHAR *, CHAR *, 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)); @@ -39,15 +45,16 @@ FCT (pattern, string, flags) se = string + STRLEN ((XCHAR *)string); pe = pattern + STRLEN ((XCHAR *)pattern); - return (GMATCH (string, se, pattern, pe, flags)); + return (GMATCH (string, se, pattern, pe, (struct STRUCT *)NULL, flags)); } /* Match STRING against the filename pattern PATTERN, returning zero if it matches, FNM_NOMATCH if not. */ static int -GMATCH (string, se, pattern, pe, flags) +GMATCH (string, se, pattern, pe, ends, flags) CHAR *string, *se; CHAR *pattern, *pe; + struct STRUCT *ends; int flags; { CHAR *p, *n; /* pattern, string */ @@ -103,6 +110,9 @@ fprintf(stderr, "gmatch: pattern = %s; pe = %s\n", pattern, pe); break; case L('\\'): /* backslash escape removes special meaning */ + if (p == pe && sc == '\\' && (n+1 == se)) + break; + if (p == pe) return FNM_NOMATCH; @@ -118,7 +128,16 @@ fprintf(stderr, "gmatch: pattern = %s; pe = %s\n", pattern, pe); return FNM_NOMATCH; break; - case '*': /* Match zero or more characters */ + case L('*'): /* Match zero or more characters */ + /* See below for the reason for using this. It avoids backtracking + back to a previous `*'. Picked up from glibc. */ + if (ends != NULL) + { + ends->pattern = p - 1; + ends->string = n; + return (0); + } + if ((flags & FNM_PERIOD) && sc == L('.') && (n == string || ((flags & FNM_PATHNAME) && n[-1] == L('/')))) /* `*' cannot match a `.' if it is the first character of the @@ -141,17 +160,9 @@ fprintf(stderr, "gmatch: pattern = %s; pe = %s\n", pattern, pe); { CHAR *newn; -#if 0 - for (newn = n; newn < se; ++newn) - { - if (EXTMATCH (c, newn, se, p, pe, flags) == 0) - return (0); - } -#else /* We can match 0 or 1 times. If we match, return success */ if (EXTMATCH (c, n, se, p, pe, flags) == 0) return (0); -#endif /* We didn't match the extended glob pattern, but that's OK, since we can match 0 or 1 occurrences. @@ -241,7 +252,7 @@ fprintf(stderr, "gmatch: pattern = %s; pe = %s\n", pattern, pe); { while (n < se && *n != L('/')) ++n; - if (n < se && *n == L('/') && (GMATCH (n+1, se, p, pe, flags) == 0)) + if (n < se && *n == L('/') && (GMATCH (n+1, se, p, pe, NULL, flags) == 0)) return 0; return FNM_NOMATCH; /* XXX */ } @@ -250,10 +261,13 @@ fprintf(stderr, "gmatch: pattern = %s; pe = %s\n", pattern, pe); { U_CHAR c1; const CHAR *endp; + struct STRUCT end; + end.pattern = NULL; endp = MEMCHR (n, (flags & FNM_PATHNAME) ? L('/') : L('\0'), se - n); if (endp == 0) endp = se; + c1 = ((flags & FNM_NOESCAPE) == 0 && c == L('\\')) ? *p : c; c1 = FOLD (c1); for (--p; n < endp; ++n) @@ -272,9 +286,24 @@ fprintf(stderr, "gmatch: pattern = %s; pe = %s\n", pattern, pe); continue; /* Otherwise, we just recurse. */ - if (GMATCH (n, se, p, pe, flags & ~FNM_PERIOD) == 0) - return (0); + if (GMATCH (n, se, p, pe, &end, flags & ~FNM_PERIOD) == 0) + { + if (end.pattern == NULL) + return (0); + break; + } + } + /* This is a clever idea from glibc, used to avoid backtracking + to a `*' that appears earlier in the pattern. We get away + without saving se and pe because they are always the same, + even in the recursive calls to gmatch */ + if (end.pattern != NULL) + { + p = end.pattern; + n = end.string; + continue; } + return FNM_NOMATCH; } @@ -355,11 +384,13 @@ BRACKMATCH (p, test, flags) { register CHAR cstart, cend, c; register int not; /* Nonzero if the sense of the character class is inverted. */ - int brcnt, forcecoll; + int brcnt, brchr, forcecoll; INT pc; CHAR *savep; + U_CHAR orig_test; - test = FOLD (test); + orig_test = test; + test = FOLD (orig_test); savep = p; @@ -424,12 +455,23 @@ BRACKMATCH (p, test, flags) { bcopy (p + 1, ccname, (close - p - 1) * sizeof (CHAR)); *(ccname + (close - p - 1)) = L('\0'); - pc = IS_CCLASS (test, (XCHAR *)ccname); + pc = IS_CCLASS (orig_test, (XCHAR *)ccname); } if (pc == -1) - pc = 0; + { + /* CCNAME is not a valid character class in the current + locale. In addition to noting no match (pc = 0), we have + a choice about what to do with the invalid charclass. + Posix leaves the behavior unspecified, but we're going + to skip over the charclass and keep going instead of + testing ORIG_TEST against each character in the class + string. If we don't want to do that, take out the update + of P. */ + pc = 0; + p = close + 2; + } else - p = close + 2; + p = close + 2; /* move past the closing `]' */ free (ccname); } @@ -546,16 +588,26 @@ matched: /* Skip the rest of the [...] that already matched. */ c = *--p; brcnt = 1; + brchr = 0; while (brcnt > 0) { + int oc; + /* A `[' without a matching `]' is just another character to match. */ if (c == L('\0')) return ((test == L('[')) ? savep : (CHAR *)0); + oc = c; c = *p++; if (c == L('[') && (*p == L('=') || *p == L(':') || *p == L('.'))) - brcnt++; - else if (c == L(']')) + { + brcnt++; + brchr = *p; + } + /* 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--; else if (!(flags & FNM_NOESCAPE) && c == L('\\')) { @@ -748,7 +800,7 @@ fprintf(stderr, "extmatch: flags = %d\n", flags); /* If we can get away with no matches, don't even bother. Just call GMATCH on the rest of the pattern and return success if it succeeds. */ - if (xc == L('*') && (GMATCH (s, se, prest, pe, flags) == 0)) + if (xc == L('*') && (GMATCH (s, se, prest, pe, NULL, flags) == 0)) return 0; /* OK, we have to do this the hard way. First, we make sure one of @@ -761,7 +813,7 @@ fprintf(stderr, "extmatch: flags = %d\n", flags); { /* Match this substring (S -> SREST) against this subpattern (psub -> pnext - 1) */ - m1 = GMATCH (s, srest, psub, pnext - 1, flags) == 0; + m1 = GMATCH (s, srest, psub, pnext - 1, NULL, flags) == 0; /* OK, we matched a subpattern, so make sure the rest of the string matches the rest of the pattern. Also handle multiple matches of the pattern. */ @@ -769,8 +821,8 @@ fprintf(stderr, "extmatch: flags = %d\n", flags); { /* if srest > s, we are not at start of string */ xflags = (srest > s) ? (flags & ~FNM_PERIOD) : flags; - m2 = (GMATCH (srest, se, prest, pe, xflags) == 0) || - (s != srest && GMATCH (srest, se, p - 1, pe, xflags) == 0); + m2 = (GMATCH (srest, se, prest, pe, NULL, xflags) == 0) || + (s != srest && GMATCH (srest, se, p - 1, pe, NULL, xflags) == 0); } if (m1 && m2) return (0); @@ -785,7 +837,7 @@ fprintf(stderr, "extmatch: flags = %d\n", flags); /* If we can get away with no matches, don't even bother. Just call gmatch on the rest of the pattern and return success if it succeeds. */ - if (xc == L('?') && (GMATCH (s, se, prest, pe, flags) == 0)) + if (xc == L('?') && (GMATCH (s, se, prest, pe, NULL, flags) == 0)) return 0; /* OK, we have to do this the hard way. First, we see if one of @@ -799,8 +851,8 @@ fprintf(stderr, "extmatch: flags = %d\n", flags); { /* if srest > s, we are not at start of string */ xflags = (srest > s) ? (flags & ~FNM_PERIOD) : flags; - if (GMATCH (s, srest, psub, pnext - 1, flags) == 0 && - GMATCH (srest, se, prest, pe, xflags) == 0) + if (GMATCH (s, srest, psub, pnext - 1, NULL, flags) == 0 && + GMATCH (srest, se, prest, pe, NULL, xflags) == 0) return (0); } if (pnext == prest) @@ -816,14 +868,21 @@ fprintf(stderr, "extmatch: flags = %d\n", flags); { pnext = PATSCAN (psub, pe, L('|')); /* If one of the patterns matches, just bail immediately. */ - if (m1 = (GMATCH (s, srest, psub, pnext - 1, flags) == 0)) + if (m1 = (GMATCH (s, srest, psub, pnext - 1, NULL, flags) == 0)) break; if (pnext == prest) break; } + + /* If nothing matched, but the string starts with a period and we + need to match periods explicitly, don't return this as a match, + even for negation. Might need to do this only if srest == s. */ + if (m1 == 0 && *s == '.' && (flags & FNM_PERIOD)) + return (FNM_NOMATCH); + /* if srest > s, we are not at start of string */ xflags = (srest > s) ? (flags & ~FNM_PERIOD) : flags; - if (m1 == 0 && GMATCH (srest, se, prest, pe, xflags) == 0) + if (m1 == 0 && GMATCH (srest, se, prest, pe, NULL, xflags) == 0) return (0); } return (FNM_NOMATCH); @@ -847,6 +906,7 @@ fprintf(stderr, "extmatch: flags = %d\n", flags); #undef PATSCAN #undef STRCOMPARE #undef EXTMATCH +#undef STRUCT #undef BRACKMATCH #undef STRCHR #undef STRCOLL diff --git a/lib/glob/smatch.c b/lib/glob/smatch.c index edc5b95d..025fe4fc 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-2011 Free Software Foundation, Inc. +/* Copyright (C) 1991-2017 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne Again SHell. @@ -144,25 +144,33 @@ static char const *const cclass_name[] = #define N_CHAR_CLASS (sizeof(cclass_name) / sizeof (cclass_name[0])) -static int -is_cclass (c, name) - int c; +static enum char_class +is_valid_cclass (name) const char *name; { - enum char_class char_class = CC_NO_CLASS; - int i, result; + enum char_class ret; + int i; + + ret = CC_NO_CLASS; for (i = 1; i < N_CHAR_CLASS; i++) { if (STREQ (name, cclass_name[i])) { - char_class = (enum char_class)i; + ret = (enum char_class)i; break; } } - if (char_class == 0) - return -1; + return ret; +} + +static int +cclass_test (c, char_class) + int c; + enum char_class char_class; +{ + int result; switch (char_class) { @@ -215,6 +223,22 @@ is_cclass (c, name) return result; } + +static int +is_cclass (c, name) + int c; + const char *name; +{ + enum char_class char_class; + int result; + + char_class = is_valid_cclass (name); + if (char_class == CC_NO_CLASS) + return -1; + + result = cclass_test (c, char_class); + return (result); +} /* Now include `sm_loop.c' for single-byte characters. */ /* The result of FOLD is an `unsigned char' */ @@ -230,6 +254,7 @@ is_cclass (c, name) #define PATSCAN glob_patscan #define STRCOMPARE strcompare #define EXTMATCH extmatch +#define STRUCT smat_struct #define STRCHR(S, C) strchr((S), (C)) #define MEMCHR(S, C, N) memchr((S), (C), (N)) #define STRCOLL(S1, S2) strcoll((S1), (S2)) @@ -355,6 +380,50 @@ is_wcclass (wc, name) return (iswctype (wc, desc)); } +/* Return 1 if there are no char class [:class:] expressions (degenerate case) + or only posix-specified (C locale supported) char class expressions in + PATTERN. These are the ones where it's safe to punt to the single-byte + code, since wide character support allows locale-defined char classes. + This only uses single-byte code, but is only needed to support multibyte + locales. */ +static int +posix_cclass_only (pattern) + char *pattern; +{ + char *p, *p1; + char cc[16]; /* sufficient for all valid posix char class names */ + enum char_class valid; + + p = pattern; + while (p = strchr (p, '[')) + { + if (p[1] != ':') + { + p++; + continue; + } + p += 2; /* skip past "[:" */ + /* Find end of char class expression */ + for (p1 = p; *p1; p1++) + if (*p1 == ':' && p1[1] == ']') + break; + if (*p1 == 0) /* no char class expression found */ + break; + /* Find char class name and validate it against posix char classes */ + if ((p1 - p) >= sizeof (cc)) + return 0; + bcopy (p, cc, p1 - p); + cc[p1 - p] = '\0'; + valid = is_valid_cclass (cc); + if (valid == CC_NO_CLASS) + return 0; /* found unrecognized char class name */ + + p = p1 + 2; /* found posix char class name */ + } + + return 1; /* no char class names or only posix */ +} + /* Now include `sm_loop.c' for multibyte characters. */ #define FOLD(c) ((flags & FNM_CASEFOLD) && iswupper (c) ? towlower (c) : (c)) #define FCT internal_wstrmatch @@ -365,6 +434,7 @@ is_wcclass (wc, name) #define PATSCAN glob_patscan_wc #define STRCOMPARE wscompare #define EXTMATCH extmatch_wc +#define STRUCT wcsmat_struct #define STRCHR(S, C) wcschr((S), (C)) #define MEMCHR(S, C, N) wmemchr((S), (C), (N)) #define STRCOLL(S1, S2) wcscoll((S1), (S2)) @@ -390,10 +460,10 @@ xstrmatch (pattern, string, flags) wchar_t *wpattern, *wstring; size_t plen, slen, mplen, mslen; - if (mbsmbchar (string) == 0 && mbsmbchar (pattern) == 0) + if (MB_CUR_MAX == 1) return (internal_strmatch ((unsigned char *)pattern, (unsigned char *)string, flags)); - if (MB_CUR_MAX == 1) + 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.h b/lib/glob/strmatch.h index 5c99e0ca..aee00cc8 100644 --- a/lib/glob/strmatch.h +++ b/lib/glob/strmatch.h @@ -46,6 +46,8 @@ #define FNM_CASEFOLD (1 << 4) /* Compare without regard to case. */ #define FNM_EXTMATCH (1 << 5) /* Use ksh-like extended matching. */ +#define FNM_FIRSTCHAR (1 << 6) /* Match only the first character */ + /* Value returned by `strmatch' if STRING does not match PATTERN. */ #undef FNM_NOMATCH diff --git a/lib/malloc/malloc.c b/lib/malloc/malloc.c index 053305fc..88d777e5 100644 --- a/lib/malloc/malloc.c +++ b/lib/malloc/malloc.c @@ -81,7 +81,7 @@ #else # include <strings.h> #endif - +#include <errno.h> #include <stdio.h> /* Define getpagesize () if the system does not. */ @@ -100,6 +100,12 @@ # include "watch.h" #endif +#ifdef powerof2 +# undef powerof2 +#endif +/* Could also use (((x) & -(x)) == (x)) */ +#define powerof2(x) ((((x) - 1) & (x)) == 0) + /* System-specific omissions. */ #ifdef HPUX # define NO_VALLOC @@ -240,6 +246,10 @@ static const unsigned long binsizes[NBUCKETS] = { /* binsizes[x] == (1 << ((x) + 3)) */ #define binsize(x) binsizes[(x)] +#if !defined (errno) +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)); @@ -1033,11 +1043,15 @@ internal_realloc (mem, n, file, line, flags) _mstats.bytesreq += (n < tocopy) ? 0 : n - tocopy; #endif + /* If we're reallocating to the same size as previously, return now */ + if (n == p->mh_nbytes) + return mem; + /* See if desired size rounds to same power of 2 as actual size. */ nbytes = ALLOCATED_BYTES(n); /* If ok, use the same block, just marking its size as changed. */ - if (RIGHT_BUCKET(nbytes, nunits)) + if (RIGHT_BUCKET(nbytes, nunits) || RIGHT_BUCKET(nbytes, nunits-1)) { #if 0 m = (char *)mem + p->mh_nbytes; @@ -1121,6 +1135,57 @@ internal_memalign (alignment, size, file, line, flags) return aligned; } +int +posix_memalign (memptr, alignment, size) + void **memptr; + size_t alignment, size; +{ + void *mem; + + /* Perform posix-mandated error checking here */ + if ((alignment % sizeof (void *) != 0) || alignment == 0) + return EINVAL; + else if (powerof2 (alignment) == 0) + return EINVAL; + + mem = internal_memalign (alignment, size, (char *)0, 0, 0); + if (mem != 0) + { + *memptr = mem; + return 0; + } + return ENOMEM; +} + +size_t +malloc_usable_size (mem) + void *mem; +{ + register union mhead *p; + register char *ap; + register int maxbytes; + + + if ((ap = (char *)mem) == 0) + return 0; + + /* Find the true start of the memory block to discover which bin */ + p = (union mhead *) ap - 1; + if (p->mh_alloc == ISMEMALIGN) + { + ap -= p->mh_nbytes; + p = (union mhead *) ap - 1; + } + + /* XXX - should we return 0 if ISFREE? */ + maxbytes = binsize(p->mh_index); + + /* So the usable size is the maximum number of bytes in the bin less the + malloc overhead */ + maxbytes -= MOVERHEAD + MSLOP; + return (maxbytes); +} + #if !defined (NO_VALLOC) /* This runs into trouble with getpagesize on HPUX, and Multimax machines. Patching out seems cleaner than the ugly fix needed. */ diff --git a/lib/readline/Makefile.in b/lib/readline/Makefile.in index 1291249d..b2358c67 100644 --- a/lib/readline/Makefile.in +++ b/lib/readline/Makefile.in @@ -64,7 +64,8 @@ LOCAL_DEFS = @LOCAL_DEFS@ INCLUDES = -I. -I$(BUILD_DIR) -I$(topdir) -I$(topdir)/lib -CCFLAGS = $(DEFS) $(LOCAL_DEFS) $(APP_CFLAGS) $(CPPFLAGS) ${INCLUDES} $(LOCAL_CFLAGS) $(CFLAGS) +CCFLAGS = $(DEFS) $(LOCAL_DEFS) $(APP_CFLAGS) $(CPPFLAGS) ${INCLUDES} \ + $(LOCAL_CFLAGS) $(CFLAGS) ${ADDON_CFLAGS} .c.o: ${RM} $@ diff --git a/lib/readline/bind.c b/lib/readline/bind.c index f1098c48..2e05b460 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-2016 Free Software Foundation, Inc. +/* Copyright (C) 1987-2017 Free Software Foundation, Inc. This file is part of the GNU Readline Library (Readline), a library for reading lines of text with interactive input and history editing. @@ -80,6 +80,8 @@ static void _rl_init_file_error (const char *, ...) __attribute__((__format__ ( static void _rl_init_file_error (); #endif +static rl_command_func_t *_rl_function_of_keyseq_internal PARAMS((const char *, size_t, Keymap, int *)); + static char *_rl_read_file PARAMS((char *, size_t *)); static int _rl_read_init_file PARAMS((const char *, int)); static int glean_key_from_name PARAMS((char *)); @@ -87,6 +89,9 @@ static int glean_key_from_name PARAMS((char *)); static int find_boolean_var PARAMS((const char *)); static int find_string_var PARAMS((const char *)); +static const char *boolean_varname PARAMS((int)); +static const char *string_varname PARAMS((int)); + static char *_rl_get_string_variable_value PARAMS((const char *)); static int substring_member_of_array PARAMS((const char *, const char * const *)); @@ -95,6 +100,16 @@ static int currently_reading_init_file; /* used only in this file */ static int _rl_prefer_visible_bell = 1; +#define OP_EQ 1 +#define OP_NE 2 +#define OP_GT 3 +#define OP_GE 4 +#define OP_LT 5 +#define OP_LE 6 + +#define OPSTART(c) ((c) == '=' || (c) == '!' || (c) == '<' || (c) == '>') +#define CMPSTART(c) ((c) == '=' || (c) == '!') + /* **************************************************************** */ /* */ /* Binding keys */ @@ -105,10 +120,7 @@ static int _rl_prefer_visible_bell = 1; Add NAME to the list of named functions. Make FUNCTION be the function that gets called. If KEY is not -1, then bind it. */ int -rl_add_defun (name, function, key) - const char *name; - rl_command_func_t *function; - int key; +rl_add_defun (const char *name, rl_command_func_t *function, int key) { if (key != -1) rl_bind_key (key, function); @@ -118,9 +130,7 @@ rl_add_defun (name, function, key) /* Bind KEY to FUNCTION. Returns non-zero if KEY is out of range. */ int -rl_bind_key (key, function) - int key; - rl_command_func_t *function; +rl_bind_key (int key, rl_command_func_t *function) { char keyseq[3]; int l; @@ -168,10 +178,7 @@ rl_bind_key (key, function) /* Bind KEY to FUNCTION in MAP. Returns non-zero in case of invalid KEY. */ int -rl_bind_key_in_map (key, function, map) - int key; - rl_command_func_t *function; - Keymap map; +rl_bind_key_in_map (int key, rl_command_func_t *function, Keymap map) { int result; Keymap oldmap; @@ -184,57 +191,44 @@ rl_bind_key_in_map (key, function, map) } /* Bind key sequence KEYSEQ to DEFAULT_FUNC if KEYSEQ is unbound. Right - now, this is always used to attempt to bind the arrow keys, hence the - check for rl_vi_movement_mode. */ + now, this is always used to attempt to bind the arrow keys. */ int -rl_bind_key_if_unbound_in_map (key, default_func, kmap) - int key; - rl_command_func_t *default_func; - Keymap kmap; +rl_bind_key_if_unbound_in_map (int key, rl_command_func_t *default_func, Keymap kmap) { - char keyseq[2]; + char *keyseq; - keyseq[0] = (unsigned char)key; - keyseq[1] = '\0'; + keyseq = rl_untranslate_keyseq ((unsigned char)key); return (rl_bind_keyseq_if_unbound_in_map (keyseq, default_func, kmap)); } int -rl_bind_key_if_unbound (key, default_func) - int key; - rl_command_func_t *default_func; +rl_bind_key_if_unbound (int key, rl_command_func_t *default_func) { - char keyseq[2]; + char *keyseq; - keyseq[0] = (unsigned char)key; - keyseq[1] = '\0'; + keyseq = rl_untranslate_keyseq ((unsigned char)key); return (rl_bind_keyseq_if_unbound_in_map (keyseq, default_func, _rl_keymap)); } /* Make KEY do nothing in the currently selected keymap. - Returns non-zero in case of error. */ + Returns non-zero in case of error. This is not the same as self-insert; + this makes it a dead key. */ int -rl_unbind_key (key) - int key; +rl_unbind_key (int key) { return (rl_bind_key (key, (rl_command_func_t *)NULL)); } -/* Make KEY do nothing in MAP. - Returns non-zero in case of error. */ +/* Make KEY do nothing in MAP. Returns non-zero in case of error. */ int -rl_unbind_key_in_map (key, map) - int key; - Keymap map; +rl_unbind_key_in_map (int key, Keymap map) { return (rl_bind_key_in_map (key, (rl_command_func_t *)NULL, map)); } /* Unbind all keys bound to FUNCTION in MAP. */ int -rl_unbind_function_in_map (func, map) - rl_command_func_t *func; - Keymap map; +rl_unbind_function_in_map (rl_command_func_t *func, Keymap map) { register int i, rval; @@ -249,10 +243,9 @@ rl_unbind_function_in_map (func, map) return rval; } +/* Unbind all keys bound to COMMAND, which is a bindable command name, in MAP */ int -rl_unbind_command_in_map (command, map) - const char *command; - Keymap map; +rl_unbind_command_in_map (const char *command, Keymap map) { rl_command_func_t *func; @@ -266,9 +259,7 @@ rl_unbind_command_in_map (command, map) FUNCTION, starting in the current keymap. This makes new keymaps as necessary. */ int -rl_bind_keyseq (keyseq, function) - const char *keyseq; - rl_command_func_t *function; +rl_bind_keyseq (const char *keyseq, rl_command_func_t *function) { return (rl_generic_bind (ISFUNC, keyseq, (char *)function, _rl_keymap)); } @@ -277,20 +268,14 @@ rl_bind_keyseq (keyseq, function) FUNCTION. This makes new keymaps as necessary. The initial place to do bindings is in MAP. */ int -rl_bind_keyseq_in_map (keyseq, function, map) - const char *keyseq; - rl_command_func_t *function; - Keymap map; +rl_bind_keyseq_in_map (const char *keyseq, rl_command_func_t *function, Keymap map) { return (rl_generic_bind (ISFUNC, keyseq, (char *)function, map)); } /* Backwards compatibility; equivalent to rl_bind_keyseq_in_map() */ int -rl_set_key (keyseq, function, map) - const char *keyseq; - rl_command_func_t *function; - Keymap map; +rl_set_key (const char *keyseq, rl_command_func_t *function, Keymap map) { return (rl_generic_bind (ISFUNC, keyseq, (char *)function, map)); } @@ -299,16 +284,24 @@ rl_set_key (keyseq, function, map) now, this is always used to attempt to bind the arrow keys, hence the check for rl_vi_movement_mode. */ int -rl_bind_keyseq_if_unbound_in_map (keyseq, default_func, kmap) - const char *keyseq; - rl_command_func_t *default_func; - Keymap kmap; +rl_bind_keyseq_if_unbound_in_map (const char *keyseq, rl_command_func_t *default_func, Keymap kmap) { rl_command_func_t *func; + char *keys; + int keys_len; if (keyseq) { - func = rl_function_of_keyseq (keyseq, kmap, (int *)NULL); + /* Handle key sequences that require translations and `raw' ones that + don't. This might be a problem with backslashes. */ + keys = (char *)xmalloc (1 + (2 * strlen (keyseq))); + if (rl_translate_keyseq (keyseq, keys, &keys_len)) + { + xfree (keys); + return -1; + } + func = rl_function_of_keyseq_len (keys, keys_len, kmap, (int *)NULL); + xfree (keys); #if defined (VI_MODE) if (!func || func == rl_do_lowercase_version || func == rl_vi_movement_mode) #else @@ -322,9 +315,7 @@ rl_bind_keyseq_if_unbound_in_map (keyseq, default_func, kmap) } int -rl_bind_keyseq_if_unbound (keyseq, default_func) - const char *keyseq; - rl_command_func_t *default_func; +rl_bind_keyseq_if_unbound (const char *keyseq, rl_command_func_t *default_func) { return (rl_bind_keyseq_if_unbound_in_map (keyseq, default_func, _rl_keymap)); } @@ -333,9 +324,7 @@ rl_bind_keyseq_if_unbound (keyseq, default_func) the string of characters MACRO. This makes new keymaps as necessary. The initial place to do bindings is in MAP. */ int -rl_macro_bind (keyseq, macro, map) - const char *keyseq, *macro; - Keymap map; +rl_macro_bind (const char *keyseq, const char *macro, Keymap map) { char *macro_keys; int macro_keys_len; @@ -357,16 +346,13 @@ rl_macro_bind (keyseq, macro, map) a macro (ISMACR), or a keymap (ISKMAP). This makes new keymaps as necessary. The initial place to do bindings is in MAP. */ int -rl_generic_bind (type, keyseq, data, map) - int type; - const char *keyseq; - char *data; - Keymap map; +rl_generic_bind (int type, const char *keyseq, char *data, Keymap map) { char *keys; - int keys_len; + int keys_len, prevkey; register int i; KEYMAP_ENTRY k; + Keymap prevmap; k.function = 0; @@ -389,12 +375,18 @@ rl_generic_bind (type, keyseq, data, map) return -1; } + prevmap = map; + prevkey = keys[0]; + /* Bind keys, making new keymaps as necessary. */ for (i = 0; i < keys_len; i++) { unsigned char uc = keys[i]; int ic; + if (i > 0) + prevkey = ic; + ic = uc; if (ic < 0 || ic >= KEYMAP_SIZE) { @@ -406,7 +398,10 @@ rl_generic_bind (type, keyseq, data, map) { ic = UNMETA (ic); if (map[ESC].type == ISKMAP) - map = FUNCTION_TO_KEYMAP (map, ESC); + { + prevmap = map; + map = FUNCTION_TO_KEYMAP (map, ESC); + } } if ((i + 1) < keys_len) @@ -425,6 +420,7 @@ rl_generic_bind (type, keyseq, data, map) map[ic].type = ISKMAP; map[ic].function = KEYMAP_TO_FUNCTION (rl_make_bare_keymap()); } + prevmap = map; map = FUNCTION_TO_KEYMAP (map, ic); /* The dispatch code will return this function if no matching key sequence is found in the keymap. This (with a little @@ -444,6 +440,7 @@ rl_generic_bind (type, keyseq, data, map) xfree ((char *)map[ic].function); else if (map[ic].type == ISKMAP) { + prevmap = map; map = FUNCTION_TO_KEYMAP (map, ic); ic = ANYOTHERKEY; /* If we're trying to override a keymap with a null function @@ -460,7 +457,28 @@ rl_generic_bind (type, keyseq, data, map) } rl_binding_keymap = map; + + } + + /* If we unbound a key (type == ISFUNC, data == 0), and the prev keymap + points to the keymap where we unbound the key (sanity check), and the + current binding keymap is empty (rl_empty_keymap() returns non-zero), + and the binding keymap has ANYOTHERKEY set with type == ISFUNC + (overridden function), delete the now-empty keymap, take the previously- + overridden function and remove the override. */ + /* Right now, this only works one level back. */ + if (type == ISFUNC && data == 0 && + prevmap[prevkey].type == ISKMAP && + (FUNCTION_TO_KEYMAP(prevmap, prevkey) == rl_binding_keymap) && + rl_binding_keymap[ANYOTHERKEY].type == ISFUNC && + rl_empty_keymap (rl_binding_keymap)) + { + prevmap[prevkey].type = rl_binding_keymap[ANYOTHERKEY].type; + prevmap[prevkey].function = rl_binding_keymap[ANYOTHERKEY].function; + rl_discard_keymap (rl_binding_keymap); + rl_binding_keymap = prevmap; } + xfree (keys); return 0; } @@ -469,10 +487,7 @@ rl_generic_bind (type, keyseq, data, map) an array of characters. LEN gets the final length of ARRAY. Return non-zero if there was an error parsing SEQ. */ int -rl_translate_keyseq (seq, array, len) - const char *seq; - char *array; - int *len; +rl_translate_keyseq (const char *seq, char *array, int *len) { register int i, c, l, temp; @@ -483,7 +498,10 @@ rl_translate_keyseq (seq, array, len) c = seq[++i]; if (c == 0) - break; + { + array[l++] = '\\'; /* preserve trailing backslash */ + break; + } /* Handle \C- and \M- prefixes. */ if ((c == 'C' || c == 'M') && seq[i + 1] == '-') @@ -494,8 +512,6 @@ rl_translate_keyseq (seq, array, len) array[l++] = ESC; /* ESC is meta-prefix */ i += 5; array[l++] = CTRL (_rl_to_upper (seq[i])); - if (seq[i] == '\0') - i--; } else if (c == 'M') { @@ -524,6 +540,8 @@ rl_translate_keyseq (seq, array, len) /* Special hack for C-?... */ array[l++] = (seq[i] == '?') ? RUBOUT : CTRL (_rl_to_upper (seq[i])); } + if (seq[i] == '\0') + break; continue; } @@ -596,8 +614,7 @@ rl_translate_keyseq (seq, array, len) } static int -_rl_isescape (c) - int c; +_rl_isescape (int c) { switch (c) { @@ -613,8 +630,7 @@ _rl_isescape (c) } static int -_rl_escchar (c) - int c; +_rl_escchar (int c) { switch (c) { @@ -630,8 +646,7 @@ _rl_escchar (c) } char * -rl_untranslate_keyseq (seq) - int seq; +rl_untranslate_keyseq (int seq) { static char kseq[16]; int i, c; @@ -681,9 +696,7 @@ rl_untranslate_keyseq (seq) } char * -_rl_untranslate_macro_value (seq, use_escapes) - char *seq; - int use_escapes; +_rl_untranslate_macro_value (char *seq, int use_escapes) { char *ret, *r, *s; int c; @@ -742,8 +755,7 @@ _rl_untranslate_macro_value (seq, use_escapes) If STRING doesn't have a matching function, then a NULL pointer is returned. */ rl_command_func_t * -rl_named_function (string) - const char *string; +rl_named_function (const char *string) { register int i; @@ -760,18 +772,15 @@ rl_named_function (string) used. TYPE, if non-NULL, is a pointer to an int which will receive the type of the object pointed to. One of ISFUNC (function), ISKMAP (keymap), or ISMACR (macro). */ -rl_command_func_t * -rl_function_of_keyseq (keyseq, map, type) - const char *keyseq; - Keymap map; - int *type; +static rl_command_func_t * +_rl_function_of_keyseq_internal (const char *keyseq, size_t len, Keymap map, int *type) { register int i; if (map == 0) map = _rl_keymap; - for (i = 0; keyseq && keyseq[i]; i++) + for (i = 0; keyseq && i < len; i++) { unsigned char ic = keyseq[i]; @@ -823,6 +832,18 @@ rl_function_of_keyseq (keyseq, map, type) return ((rl_command_func_t *) NULL); } +rl_command_func_t * +rl_function_of_keyseq (const char *keyseq, Keymap map, int *type) +{ + return _rl_function_of_keyseq_internal (keyseq, strlen (keyseq), map, type); +} + +rl_command_func_t * +rl_function_of_keyseq_len (const char *keyseq, size_t len, Keymap map, int *type) +{ + return _rl_function_of_keyseq_internal (keyseq, len, map, type); +} + /* The last key bindings file read. */ static char *last_readline_init_file = (char *)NULL; @@ -835,17 +856,20 @@ static int current_readline_init_lineno; The size of the buffer is returned in *SIZEP. Returns NULL if any errors were encountered. */ static char * -_rl_read_file (filename, sizep) - char *filename; - size_t *sizep; +_rl_read_file (char *filename, size_t *sizep) { struct stat finfo; size_t file_size; char *buffer; int i, file; - if ((stat (filename, &finfo) < 0) || (file = open (filename, O_RDONLY, 0666)) < 0) - return ((char *)NULL); + file = -1; + if (((file = open (filename, O_RDONLY, 0666)) < 0) || (fstat (file, &finfo) < 0)) + { + if (file >= 0) + close (file); + return ((char *)NULL); + } file_size = (size_t)finfo.st_size; @@ -882,8 +906,7 @@ _rl_read_file (filename, sizep) /* Re-read the current keybindings file. */ int -rl_re_read_init_file (count, ignore) - int count, ignore; +rl_re_read_init_file (int count, int ignore) { int r; r = rl_read_init_file ((const char *)NULL); @@ -900,8 +923,7 @@ rl_re_read_init_file (count, ignore) If the file existed and could be opened and read, 0 is returned, otherwise errno is returned. */ int -rl_read_init_file (filename) - const char *filename; +rl_read_init_file (const char *filename) { /* Default the filename. */ if (filename == 0) @@ -926,9 +948,7 @@ rl_read_init_file (filename) } static int -_rl_read_init_file (filename, include_level) - const char *filename; - int include_level; +_rl_read_init_file (const char *filename, int include_level) { register int i; char *buffer, *openname, *line, *end; @@ -1027,6 +1047,62 @@ _rl_init_file_error (va_alist) /* **************************************************************** */ /* */ +/* Parser Helper Functions */ +/* */ +/* **************************************************************** */ + +static int +parse_comparison_op (s, indp) + const char *s; + int *indp; +{ + int i, peekc, op; + + if (OPSTART (s[*indp]) == 0) + return -1; + i = *indp; + peekc = s[i] ? s[i+1] : 0; + op = -1; + + if (s[i] == '=') + { + op = OP_EQ; + if (peekc == '=') + i++; + i++; + } + else if (s[i] == '!' && peekc == '=') + { + op = OP_NE; + i += 2; + } + else if (s[i] == '<' && peekc == '=') + { + op = OP_LE; + i += 2; + } + else if (s[i] == '>' && peekc == '=') + { + op = OP_GE; + i += 2; + } + else if (s[i] == '<') + { + op = OP_LT; + i += 1; + } + else if (s[i] == '>') + { + op = OP_GT; + i += 1; + } + + *indp = i; + return op; +} + +/* **************************************************************** */ +/* */ /* Parser Directives */ /* */ /* **************************************************************** */ @@ -1055,10 +1131,11 @@ static int if_stack_size; /* Push _rl_parsing_conditionalized_out, and set parser state based on ARGS. */ static int -parser_if (args) - char *args; +parser_if (char *args) { - register int i; + int i, llen, boolvar, strvar; + + boolvar = strvar = -1; /* Push parser state. */ if (if_stack_depth + 1 >= if_stack_size) @@ -1075,6 +1152,8 @@ parser_if (args) if (_rl_parsing_conditionalized_out) return 0; + llen = strlen (args); + /* Isolate first argument. */ for (i = 0; args[i] && !whitespace (args[i]); i++); @@ -1117,10 +1196,138 @@ parser_if (args) _rl_parsing_conditionalized_out = mode != rl_editing_mode; } #endif /* VI_MODE */ + else if (_rl_strnicmp (args, "version", 7) == 0) + { + int rlversion, versionarg, op, previ, major, minor; + + _rl_parsing_conditionalized_out = 1; + rlversion = RL_VERSION_MAJOR*10 + RL_VERSION_MINOR; + /* if "version" is separated from the operator by whitespace, or the + operand is separated from the operator by whitespace, restore it. + We're more liberal with allowed whitespace for this variable. */ + if (i > 0 && i <= llen && args[i-1] == '\0') + args[i-1] = ' '; + args[llen] = '\0'; /* just in case */ + for (i = 7; whitespace (args[i]); i++) + ; + if (OPSTART(args[i]) == 0) + { + _rl_init_file_error ("comparison operator expected, found `%s'", args[i] ? args + i : "end-of-line"); + return 0; + } + previ = i; + op = parse_comparison_op (args, &i); + if (op <= 0) + { + _rl_init_file_error ("comparison operator expected, found `%s'", args+previ); + return 0; + } + for ( ; args[i] && whitespace (args[i]); i++) + ; + if (args[i] == 0 || _rl_digit_p (args[i]) == 0) + { + _rl_init_file_error ("numeric argument expected, found `%s'", args+i); + return 0; + } + major = minor = 0; + previ = i; + for ( ; args[i] && _rl_digit_p (args[i]); i++) + major = major*10 + _rl_digit_value (args[i]); + if (args[i] == '.') + { + if (args[i + 1] && _rl_digit_p (args [i + 1]) == 0) + { + _rl_init_file_error ("numeric argument expected, found `%s'", args+previ); + return 0; + } + for (++i; args[i] && _rl_digit_p (args[i]); i++) + minor = minor*10 + _rl_digit_value (args[i]); + } + /* optional - check for trailing garbage on the line, allow whitespace + and a trailing comment */ + previ = i; + for ( ; args[i] && whitespace (args[i]); i++) + ; + if (args[i] && args[i] != '#') + { + _rl_init_file_error ("trailing garbage on line: `%s'", args+previ); + return 0; + } + versionarg = major*10 + minor; + + switch (op) + { + case OP_EQ: + _rl_parsing_conditionalized_out = rlversion == versionarg; + break; + case OP_NE: + _rl_parsing_conditionalized_out = rlversion != versionarg; + break; + case OP_GT: + _rl_parsing_conditionalized_out = rlversion > versionarg; + break; + case OP_GE: + _rl_parsing_conditionalized_out = rlversion >= versionarg; + break; + case OP_LT: + _rl_parsing_conditionalized_out = rlversion < versionarg; + break; + case OP_LE: + _rl_parsing_conditionalized_out = rlversion <= versionarg; + break; + } + } /* Check to see if the first word in ARGS is the same as the value stored in rl_readline_name. */ else if (_rl_stricmp (args, rl_readline_name) == 0) _rl_parsing_conditionalized_out = 0; + else if ((boolvar = find_boolean_var (args)) >= 0 || (strvar = find_string_var (args)) >= 0) + { + int op, previ; + size_t vlen; + const char *vname; + char *valuearg, *vval, prevc; + + _rl_parsing_conditionalized_out = 1; + vname = (boolvar >= 0) ? boolean_varname (boolvar) : string_varname (strvar); + vlen = strlen (vname); + if (i > 0 && i <= llen && args[i-1] == '\0') + args[i-1] = ' '; + args[llen] = '\0'; /* just in case */ + for (i = vlen; whitespace (args[i]); i++) + ; + if (CMPSTART(args[i]) == 0) + { + _rl_init_file_error ("equality comparison operator expected, found `%s'", args[i] ? args + i : "end-of-line"); + return 0; + } + previ = i; + op = parse_comparison_op (args, &i); + if (op != OP_EQ && op != OP_NE) + { + _rl_init_file_error ("equality comparison operator expected, found `%s'", args+previ); + return 0; + } + for ( ; args[i] && whitespace (args[i]); i++) + ; + if (args[i] == 0) + { + _rl_init_file_error ("argument expected, found `%s'", args+i); + return 0; + } + previ = i; + valuearg = args + i; + for ( ; args[i] && whitespace (args[i]) == 0; i++) + ; + prevc = args[i]; + args[i] = '\0'; /* null-terminate valuearg */ + vval = rl_variable_value (vname); + if (op == OP_EQ) + _rl_parsing_conditionalized_out = _rl_stricmp (vval, valuearg) != 0; + else if (op == OP_NE) + _rl_parsing_conditionalized_out = _rl_stricmp (vval, valuearg) == 0; + args[i] = prevc; + } else _rl_parsing_conditionalized_out = 1; return 0; @@ -1128,8 +1335,7 @@ parser_if (args) /* Invert the current parser state if there is anything on the stack. */ static int -parser_else (args) - char *args; +parser_else (char *args) { register int i; @@ -1159,8 +1365,7 @@ parser_else (args) /* Terminate a conditional, popping the value of _rl_parsing_conditionalized_out from the stack. */ static int -parser_endif (args) - char *args; +parser_endif (char *args) { if (if_stack_depth) _rl_parsing_conditionalized_out = if_stack[--if_stack_depth]; @@ -1170,8 +1375,7 @@ parser_endif (args) } static int -parser_include (args) - char *args; +parser_include (char *args) { const char *old_init_file; char *e; @@ -1211,8 +1415,7 @@ static const struct { /* Handle a parser directive. STATEMENT is the line of the directive without any leading `$'. */ static int -handle_parser_directive (statement) - char *statement; +handle_parser_directive (char *statement) { register int i; char *directive, *args; @@ -1249,9 +1452,7 @@ handle_parser_directive (statement) /* Start at STRING[START] and look for DELIM. Return I where STRING[I] == DELIM or STRING[I] == 0. DELIM is usually a double quote. */ static int -_rl_skip_to_delim (string, start, delim) - char *string; - int start, delim; +_rl_skip_to_delim (char *string, int start, int delim) { int i, c, passc; @@ -1283,8 +1484,7 @@ _rl_skip_to_delim (string, start, delim) a variable binding command looks like: set variable value. A new-style keybinding looks like "\C-x\C-x": exchange-point-and-mark. */ int -rl_parse_and_bind (string) - char *string; +rl_parse_and_bind (char *string) { char *funname, *kname; register int c, i; @@ -1328,6 +1528,12 @@ rl_parse_and_bind (string) /* Advance to the colon (:) or whitespace which separates the two objects. */ for (; (c = string[i]) && c != ':' && c != ' ' && c != '\t'; i++ ); + if (i == 0) + { + _rl_init_file_error ("`%s': invalid key binding: missing key sequence", string); + return 1; + } + equivalency = (c == ':' && string[i + 1] == '='); foundsep = c != 0; @@ -1406,6 +1612,11 @@ remove_trailing: i = _rl_skip_to_delim (string, i+1, *funname); if (string[i]) i++; + else + { + _rl_init_file_error ("`%s': missing closing quote for macro", funname); + return 1; + } } /* Advance to the end of the string. */ @@ -1583,8 +1794,7 @@ static const struct { }; static int -find_boolean_var (name) - const char *name; +find_boolean_var (const char *name) { register int i; @@ -1594,12 +1804,17 @@ find_boolean_var (name) return -1; } +static const char * +boolean_varname (int i) +{ + return ((i >= 0) ? boolean_varlist[i].name : (char *)NULL); +} + /* Hooks for handling special boolean variables, where a function needs to be called or another variable needs to be changed when they're changed. */ static void -hack_special_boolean_var (i) - int i; +hack_special_boolean_var (int i) { const char *name; @@ -1668,8 +1883,7 @@ static const struct { }; static int -find_string_var (name) - const char *name; +find_string_var (const char *name) { register int i; @@ -1679,12 +1893,17 @@ find_string_var (name) return -1; } +static const char * +string_varname (int i) +{ + return ((i >= 0) ? string_varlist[i].name : (char *)NULL); +} + /* 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 values result in 0 (false). */ static int -bool_to_int (value) - const char *value; +bool_to_int (const char *value) { return (value == 0 || *value == '\0' || (_rl_stricmp (value, "on") == 0) || @@ -1692,8 +1911,7 @@ bool_to_int (value) } char * -rl_variable_value (name) - const char *name; +rl_variable_value (const char *name) { register int i; @@ -1711,8 +1929,7 @@ rl_variable_value (name) } int -rl_variable_bind (name, value) - const char *name, *value; +rl_variable_bind (const char *name, const char *value) { register int i; int v; @@ -1743,8 +1960,7 @@ rl_variable_bind (name, value) } static int -sv_editmode (value) - const char *value; +sv_editmode (const char *value) { if (_rl_strnicmp (value, "vi", 2) == 0) { @@ -1764,8 +1980,7 @@ sv_editmode (value) } static int -sv_combegin (value) - const char *value; +sv_combegin (const char *value) { if (value && *value) { @@ -1777,8 +1992,7 @@ sv_combegin (value) } static int -sv_dispprefix (value) - const char *value; +sv_dispprefix (const char *value) { int nval = 0; @@ -1793,8 +2007,7 @@ sv_dispprefix (value) } static int -sv_compquery (value) - const char *value; +sv_compquery (const char *value) { int nval = 100; @@ -1809,8 +2022,7 @@ sv_compquery (value) } static int -sv_compwidth (value) - const char *value; +sv_compwidth (const char *value) { int nval = -1; @@ -1822,8 +2034,7 @@ sv_compwidth (value) } static int -sv_histsize (value) - const char *value; +sv_histsize (const char *value) { int nval; @@ -1842,8 +2053,7 @@ sv_histsize (value) } static int -sv_keymap (value) - const char *value; +sv_keymap (const char *value) { Keymap kmap; @@ -1857,8 +2067,7 @@ sv_keymap (value) } static int -sv_seqtimeout (value) - const char *value; +sv_seqtimeout (const char *value) { int nval; @@ -1874,8 +2083,7 @@ sv_seqtimeout (value) } static int -sv_bell_style (value) - const char *value; +sv_bell_style (const char *value) { if (value == 0 || *value == '\0') _rl_bell_preference = AUDIBLE_BELL; @@ -1891,8 +2099,7 @@ sv_bell_style (value) } static int -sv_isrchterm (value) - const char *value; +sv_isrchterm (const char *value) { int beg, end, delim; char *v; @@ -1929,8 +2136,7 @@ sv_isrchterm (value) extern char *_rl_emacs_mode_str; static int -sv_emacs_modestr (value) - const char *value; +sv_emacs_modestr (const char *value) { if (value && *value) { @@ -1958,8 +2164,7 @@ sv_emacs_modestr (value) } static int -sv_viins_modestr (value) - const char *value; +sv_viins_modestr (const char *value) { if (value && *value) { @@ -1987,8 +2192,7 @@ sv_viins_modestr (value) } static int -sv_vicmd_modestr (value) - const char *value; +sv_vicmd_modestr (const char *value) { if (value && *value) { @@ -2039,8 +2243,7 @@ static const assoc_list name_key_alist[] = { }; static int -glean_key_from_name (name) - char *name; +glean_key_from_name (char *name) { register int i; @@ -2070,8 +2273,7 @@ static const struct { }; Keymap -rl_get_keymap_by_name (name) - const char *name; +rl_get_keymap_by_name (const char *name) { register int i; @@ -2082,8 +2284,7 @@ rl_get_keymap_by_name (name) } char * -rl_get_keymap_name (map) - Keymap map; +rl_get_keymap_name (Keymap map) { register int i; for (i = 0; keymap_names[i].name; i++) @@ -2093,21 +2294,20 @@ rl_get_keymap_name (map) } void -rl_set_keymap (map) - Keymap map; +rl_set_keymap (Keymap map) { if (map) _rl_keymap = map; } Keymap -rl_get_keymap () +rl_get_keymap (void) { return (_rl_keymap); } void -rl_set_keymap_from_edit_mode () +rl_set_keymap_from_edit_mode (void) { if (rl_editing_mode == emacs_mode) _rl_keymap = emacs_standard_keymap; @@ -2118,7 +2318,7 @@ rl_set_keymap_from_edit_mode () } char * -rl_get_keymap_name_from_edit_mode () +rl_get_keymap_name_from_edit_mode (void) { if (rl_editing_mode == emacs_mode) return "emacs"; @@ -2143,7 +2343,7 @@ rl_get_keymap_name_from_edit_mode () /* Print the names of functions known to Readline. */ void -rl_list_funmap_names () +rl_list_funmap_names (void) { register int i; const char **funmap_names; @@ -2160,8 +2360,7 @@ rl_list_funmap_names () } static char * -_rl_get_keyname (key) - int key; +_rl_get_keyname (int key) { char *keyname; int i, c; @@ -2236,9 +2435,7 @@ _rl_get_keyname (key) /* Return a NULL terminated array of strings which represent the key sequences that are used to invoke FUNCTION in MAP. */ char ** -rl_invoking_keyseqs_in_map (function, map) - rl_command_func_t *function; - Keymap map; +rl_invoking_keyseqs_in_map (rl_command_func_t *function, Keymap map) { register int key; char **result; @@ -2345,8 +2542,7 @@ rl_invoking_keyseqs_in_map (function, map) /* Return a NULL terminated array of strings which represent the key sequences that can be used to invoke FUNCTION using the current keymap. */ char ** -rl_invoking_keyseqs (function) - rl_command_func_t *function; +rl_invoking_keyseqs (rl_command_func_t *function) { return (rl_invoking_keyseqs_in_map (function, _rl_keymap)); } @@ -2355,8 +2551,7 @@ rl_invoking_keyseqs (function) PRINT_READABLY is non-zero, then print the output in such a way that it can be read back in. */ void -rl_function_dumper (print_readably) - int print_readably; +rl_function_dumper (int print_readably) { register int i; const char **names; @@ -2427,8 +2622,7 @@ rl_function_dumper (print_readably) rl_outstream. If an explicit argument is given, then print the output in such a way that it can be read back in. */ int -rl_dump_functions (count, key) - int count, key; +rl_dump_functions (int count, int key) { if (rl_dispatching) fprintf (rl_outstream, "\r\n"); @@ -2438,10 +2632,7 @@ rl_dump_functions (count, key) } static void -_rl_macro_dumper_internal (print_readably, map, prefix) - int print_readably; - Keymap map; - char *prefix; +_rl_macro_dumper_internal (int print_readably, Keymap map, char *prefix) { register int key; char *keyname, *out; @@ -2500,15 +2691,13 @@ _rl_macro_dumper_internal (print_readably, map, prefix) } void -rl_macro_dumper (print_readably) - int print_readably; +rl_macro_dumper (int print_readably) { _rl_macro_dumper_internal (print_readably, _rl_keymap, (char *)NULL); } int -rl_dump_macros (count, key) - int count, key; +rl_dump_macros (int count, int key) { if (rl_dispatching) fprintf (rl_outstream, "\r\n"); @@ -2518,8 +2707,7 @@ rl_dump_macros (count, key) } static char * -_rl_get_string_variable_value (name) - const char *name; +_rl_get_string_variable_value (const char *name) { static char numbuf[32]; char *ret; @@ -2599,8 +2787,7 @@ _rl_get_string_variable_value (name) } void -rl_variable_dumper (print_readably) - int print_readably; +rl_variable_dumper (int print_readably) { int i; char *v; @@ -2631,8 +2818,7 @@ rl_variable_dumper (print_readably) rl_outstream. If an explicit argument is given, then print the output in such a way that it can be read back in. */ int -rl_dump_variables (count, key) - int count, key; +rl_dump_variables (int count, int key) { if (rl_dispatching) fprintf (rl_outstream, "\r\n"); @@ -2643,9 +2829,7 @@ rl_dump_variables (count, key) /* Return non-zero if any members of ARRAY are a substring in STRING. */ static int -substring_member_of_array (string, array) - const char *string; - const char * const *array; +substring_member_of_array (const char *string, const char * const *array) { while (*array) { diff --git a/lib/readline/callback.c b/lib/readline/callback.c index cc3ce11f..a466cf9b 100644 --- a/lib/readline/callback.c +++ b/lib/readline/callback.c @@ -1,6 +1,6 @@ /* callback.c -- functions to use readline as an X `callback' mechanism. */ -/* Copyright (C) 1987-2015 Free Software Foundation, Inc. +/* Copyright (C) 1987-2017 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. @@ -60,7 +60,7 @@ int rl_persistent_signal_handlers = 0; /* **************************************************************** */ /* */ -/* Callback Readline Functions */ +/* Callback Readline Functions */ /* */ /* **************************************************************** */ @@ -80,7 +80,7 @@ static int in_handler; /* terminal_prepped and signals set? */ /* Make sure the terminal is set up, initialize readline, and prompt. */ static void -_rl_callback_newline () +_rl_callback_newline (void) { rl_initialize (); @@ -103,9 +103,7 @@ _rl_callback_newline () /* Install a readline handler, set up the terminal, and issue the prompt. */ void -rl_callback_handler_install (prompt, linefunc) - const char *prompt; - rl_vcpfunc_t *linefunc; +rl_callback_handler_install (const char *prompt, rl_vcpfunc_t *linefunc) { rl_set_prompt (prompt); RL_SETSTATE (RL_STATE_CALLBACK); @@ -126,7 +124,7 @@ rl_callback_handler_install (prompt, linefunc) /* Read one character, and dispatch to the handler if it ends the line. */ void -rl_callback_read_char () +rl_callback_read_char (void) { char *line; int eof, jcode; @@ -299,7 +297,7 @@ rl_callback_read_char () /* Remove the handler, and make sure the terminal is in its normal state. */ void -rl_callback_handler_remove () +rl_callback_handler_remove (void) { rl_linefunc = NULL; RL_UNSETSTATE (RL_STATE_CALLBACK); @@ -316,8 +314,7 @@ rl_callback_handler_remove () } _rl_callback_generic_arg * -_rl_callback_data_alloc (count) - int count; +_rl_callback_data_alloc (int count) { _rl_callback_generic_arg *arg; @@ -330,15 +327,14 @@ _rl_callback_data_alloc (count) } void -_rl_callback_data_dispose (arg) - _rl_callback_generic_arg *arg; +_rl_callback_data_dispose (_rl_callback_generic_arg *arg) { xfree (arg); } /* Make sure that this agrees with cases in rl_callback_read_char */ void -rl_callback_sigcleanup () +rl_callback_sigcleanup (void) { if (RL_ISSTATE (RL_STATE_CALLBACK) == 0) return; diff --git a/lib/readline/colors.c b/lib/readline/colors.c index 7859f5d2..53758e0e 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 + Copyright (C) 1985, 1988, 1990-1991, 1995-2010, 2012, 2015, 2017 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify @@ -37,6 +37,10 @@ #include "posixstat.h" // stat related macros (S_ISREG, ...) #include <fcntl.h> // S_ISUID +#ifndef S_ISDIR +# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) +#endif + // strlen() #if defined (HAVE_STRING_H) # include <string.h> @@ -66,7 +70,8 @@ COLOR_EXT_TYPE *_rl_color_ext_list = 0; /* Output a color indicator (which may contain nulls). */ void -_rl_put_indicator (const struct bin_str *ind) { +_rl_put_indicator (const struct bin_str *ind) +{ fwrite (ind->string, ind->len, 1, rl_outstream); } @@ -183,11 +188,17 @@ _rl_print_color_indicator (const char *f) { colored_filetype = C_FILE; +#if defined (S_ISUID) if ((mode & S_ISUID) != 0 && is_colored (C_SETUID)) colored_filetype = C_SETUID; - else if ((mode & S_ISGID) != 0 && is_colored (C_SETGID)) + else +#endif +#if defined (S_ISGID) + if ((mode & S_ISGID) != 0 && is_colored (C_SETGID)) colored_filetype = C_SETGID; - else if (is_colored (C_CAP) && 0) //f->has_capability) + else +#endif + if (is_colored (C_CAP) && 0) //f->has_capability) colored_filetype = C_CAP; else if ((mode & S_IXUGO) != 0 && is_colored (C_EXEC)) colored_filetype = C_EXEC; @@ -211,12 +222,16 @@ _rl_print_color_indicator (const char *f) colored_filetype = C_STICKY; #endif } +#if defined (S_ISLNK) else if (S_ISLNK (mode)) colored_filetype = C_LINK; +#endif else if (S_ISFIFO (mode)) colored_filetype = C_FIFO; +#if defined (S_ISSOCK) else if (S_ISSOCK (mode)) colored_filetype = C_SOCK; +#endif else if (S_ISBLK (mode)) colored_filetype = C_BLK; else if (S_ISCHR (mode)) diff --git a/lib/readline/compat.c b/lib/readline/compat.c index 2af51207..3ade3629 100644 --- a/lib/readline/compat.c +++ b/lib/readline/compat.c @@ -1,6 +1,6 @@ /* compat.c -- backwards compatibility functions. */ -/* Copyright (C) 2000-2009 Free Software Foundation, Inc. +/* Copyright (C) 2000-2017 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. @@ -46,68 +46,61 @@ extern char *rl_filename_completion_function PARAMS((const char *, int)); /* Provide backwards-compatible entry points for old function names. */ void -free_undo_list () +free_undo_list (void) { rl_free_undo_list (); } int -maybe_replace_line () +maybe_replace_line (void) { return rl_maybe_replace_line (); } int -maybe_save_line () +maybe_save_line (void) { return rl_maybe_save_line (); } int -maybe_unsave_line () +maybe_unsave_line (void) { return rl_maybe_unsave_line (); } int -ding () +ding (void) { return rl_ding (); } int -crlf () +crlf (void) { return rl_crlf (); } int -alphabetic (c) - int c; +alphabetic (int c) { return rl_alphabetic (c); } char ** -completion_matches (s, f) - const char *s; - rl_compentry_func_t *f; +completion_matches (const char *s, rl_compentry_func_t *f) { return rl_completion_matches (s, f); } char * -username_completion_function (s, i) - const char *s; - int i; +username_completion_function (const char *s, int i) { return rl_username_completion_function (s, i); } char * -filename_completion_function (s, i) - const char *s; - int i; +filename_completion_function (const char *s, int i) { return rl_filename_completion_function (s, i); } diff --git a/lib/readline/complete.c b/lib/readline/complete.c index 0a81129b..adce0d69 100644 --- a/lib/readline/complete.c +++ b/lib/readline/complete.c @@ -1,6 +1,6 @@ /* complete.c -- filename completion for readline. */ -/* Copyright (C) 1987-2015 Free Software Foundation, Inc. +/* Copyright (C) 1987-2017 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. @@ -198,15 +198,6 @@ int _rl_completion_prefix_display_length = 0; matches. If < 0 or > _rl_screenwidth, it is ignored. */ int _rl_completion_columns = -1; -/* Global variables available to applications using readline. */ - -#if defined (VISIBLE_STATS) -/* Non-zero means add an additional character to each filename displayed - during listing completion iff rl_filename_completion_desired which helps - to indicate the type of file being listed. */ -int rl_visible_stats = 0; -#endif /* VISIBLE_STATS */ - #if defined (COLOR_SUPPORT) /* Non-zero means to use colors to indicate file type when listing possible completions. The colors used are taken from $LS_COLORS, if set. */ @@ -227,6 +218,15 @@ int _rl_skip_completed_text = 0; cycle of possible completions instead of the last. */ int _rl_menu_complete_prefix_first = 0; +/* Global variables available to applications using readline. */ + +#if defined (VISIBLE_STATS) +/* Non-zero means add an additional character to each filename displayed + during listing completion iff rl_filename_completion_desired which helps + to indicate the type of file being listed. */ +int rl_visible_stats = 0; +#endif /* VISIBLE_STATS */ + /* If non-zero, then this is the address of a function to call when completing on a directory name. The function is called with the address of a string (the current directory name) as an arg. */ @@ -422,8 +422,7 @@ static int _rl_complete_display_matches_interrupt = 0; that does the initial simple matching selection algorithm (see rl_completion_matches ()). The default is to do filename completion. */ int -rl_complete (ignore, invoking_key) - int ignore, invoking_key; +rl_complete (int ignore, int invoking_key) { rl_completion_invoking_key = invoking_key; @@ -441,16 +440,14 @@ rl_complete (ignore, invoking_key) /* List the possible completions. See description of rl_complete (). */ int -rl_possible_completions (ignore, invoking_key) - int ignore, invoking_key; +rl_possible_completions (int ignore, int invoking_key) { rl_completion_invoking_key = invoking_key; return (rl_complete_internal ('?')); } int -rl_insert_completions (ignore, invoking_key) - int ignore, invoking_key; +rl_insert_completions (int ignore, int invoking_key) { rl_completion_invoking_key = invoking_key; return (rl_complete_internal ('*')); @@ -462,8 +459,7 @@ rl_insert_completions (ignore, invoking_key) an application-specific completion function to honor the show-all-if-ambiguous readline variable. */ int -rl_completion_mode (cfunc) - rl_command_func_t *cfunc; +rl_completion_mode (rl_command_func_t *cfunc) { if (rl_last_func == cfunc && !completion_changed_buffer) return '?'; @@ -483,16 +479,14 @@ rl_completion_mode (cfunc) /* Reset readline state on a signal or other event. */ void -_rl_reset_completion_state () +_rl_reset_completion_state (void) { rl_completion_found_quote = 0; rl_completion_quote_character = 0; } static void -_rl_complete_sigcleanup (sig, ptr) - int sig; - void *ptr; +_rl_complete_sigcleanup (int sig, void *ptr) { if (sig == SIGINT) /* XXX - for now */ { @@ -504,8 +498,7 @@ _rl_complete_sigcleanup (sig, ptr) /* Set default values for readline word completion. These are the variables that application completion functions can change or inspect. */ static void -set_completion_defaults (what_to_do) - int what_to_do; +set_completion_defaults (int what_to_do) { /* Only the completion entry function can change these. */ rl_filename_completion_desired = 0; @@ -523,8 +516,7 @@ set_completion_defaults (what_to_do) /* The user must press "y" or "n". Non-zero return means "y" pressed. */ static int -get_y_or_n (for_pager) - int for_pager; +get_y_or_n (int for_pager) { int c; @@ -557,8 +549,7 @@ get_y_or_n (for_pager) } static int -_rl_internal_pager (lines) - int lines; +_rl_internal_pager (int lines) { int i; @@ -575,8 +566,7 @@ _rl_internal_pager (lines) } static int -path_isdir (filename) - const char *filename; +path_isdir (const char *filename) { struct stat finfo; @@ -593,8 +583,7 @@ path_isdir (filename) `%' for character special devices `#' for block special devices */ static int -stat_char (filename) - char *filename; +stat_char (char *filename) { struct stat finfo; int character, r; @@ -625,7 +614,10 @@ stat_char (filename) #endif if (r == -1) - return (0); + { + xfree (f); + return (0); + } character = 0; if (S_ISDIR (finfo.st_mode)) @@ -675,29 +667,28 @@ stat_char (filename) #if defined (COLOR_SUPPORT) static int -colored_stat_start (filename) - const char *filename; +colored_stat_start (const char *filename) { _rl_set_normal_color (); return (_rl_print_color_indicator (filename)); } static void -colored_stat_end () +colored_stat_end (void) { _rl_prep_non_filename_text (); _rl_put_indicator (&_rl_color_indicator[C_CLR_TO_EOL]); } static int -colored_prefix_start () +colored_prefix_start (void) { _rl_set_normal_color (); return (_rl_print_prefix_color ()); } static void -colored_prefix_end () +colored_prefix_end (void) { colored_stat_end (); /* for now */ } @@ -712,8 +703,7 @@ colored_prefix_end () for the previous slash and return the portion following that. If there's no previous slash, we just return what we were passed. */ static char * -printable_part (pathname) - char *pathname; +printable_part (char *pathname) { char *temp, *x; @@ -747,8 +737,7 @@ printable_part (pathname) /* Compute width of STRING when displayed on screen by print_filename */ static int -fnwidth (string) - const char *string; +fnwidth (const char *string) { int width, pos; #if defined (HANDLE_MULTIBYTE) @@ -800,10 +789,7 @@ fnwidth (string) #define ELLIPSIS_LEN 3 static int -fnprint (to_print, prefix_bytes, real_pathname) - const char *to_print; - int prefix_bytes; - const char *real_pathname; +fnprint (const char *to_print, int prefix_bytes, const char *real_pathname) { int printed_len, w; const char *s; @@ -818,6 +804,8 @@ fnprint (to_print, prefix_bytes, real_pathname) print_len = strlen (to_print); end = to_print + print_len + 1; memset (&ps, 0, sizeof (mbstate_t)); +#else + print_len = strlen (to_print); #endif printed_len = common_prefix_len = 0; @@ -929,9 +917,7 @@ fnprint (to_print, prefix_bytes, real_pathname) filenames. Return the number of characters we output. */ static int -print_filename (to_print, full_pathname, prefix_bytes) - char *to_print, *full_pathname; - int prefix_bytes; +print_filename (char *to_print, char *full_pathname, int prefix_bytes) { int printed_len, extension_char, slen, tlen; char *s, c, *new_full_pathname, *dn; @@ -988,7 +974,6 @@ print_filename (to_print, full_pathname, prefix_bytes) slen--; else new_full_pathname[slen] = '/'; - new_full_pathname[slen] = '/'; strcpy (new_full_pathname + slen + 1, to_print); #if defined (VISIBLE_STATS) @@ -1049,10 +1034,7 @@ print_filename (to_print, full_pathname, prefix_bytes) } static char * -rl_quote_filename (s, rtype, qcp) - char *s; - int rtype; - char *qcp; +rl_quote_filename (char *s, int rtype, char *qcp) { char *r; @@ -1080,8 +1062,7 @@ rl_quote_filename (s, rtype, qcp) the value of the delimiter character that caused a word break. */ char -_rl_find_completion_word (fp, dp) - int *fp, *dp; +_rl_find_completion_word (int *fp, int *dp) { int scan, end, found_quote, delimiter, pass_next, isbrk; char quote_char, *brkchars; @@ -1213,11 +1194,7 @@ _rl_find_completion_word (fp, dp) } static char ** -gen_completion_matches (text, start, end, our_func, found_quote, quote_char) - char *text; - int start, end; - rl_compentry_func_t *our_func; - int found_quote, quote_char; +gen_completion_matches (char *text, int start, int end, rl_compentry_func_t *our_func, int found_quote, int quote_char) { char **matches; @@ -1261,8 +1238,7 @@ gen_completion_matches (text, start, end, our_func, found_quote, quote_char) /* Filter out duplicates in MATCHES. This frees up the strings in MATCHES. */ static char ** -remove_duplicate_matches (matches) - char **matches; +remove_duplicate_matches (char **matches) { char *lowest_common; int i, j, newlen; @@ -1322,10 +1298,7 @@ remove_duplicate_matches (matches) /* Find the common prefix of the list of matches, and put it into matches[0]. */ static int -compute_lcd_of_matches (match_list, matches, text) - char **match_list; - int matches; - const char *text; +compute_lcd_of_matches (char **match_list, int matches, const char *text) { register int i, c1, c2, si; int low; /* Count of max-matched characters. */ @@ -1451,7 +1424,8 @@ compute_lcd_of_matches (match_list, matches, text) } /* sort the list to get consistent answers. */ - qsort (match_list+1, matches, sizeof(char *), (QSFUNC *)_rl_qsort_string_compare); + if (rl_sort_completion_matches) + qsort (match_list+1, matches, sizeof(char *), (QSFUNC *)_rl_qsort_string_compare); si = strlen (text); lx = (si <= low) ? si : low; /* check shorter of text and matches */ @@ -1481,9 +1455,7 @@ compute_lcd_of_matches (match_list, matches, text) } static int -postprocess_matches (matchesp, matching_filenames) - char ***matchesp; - int matching_filenames; +postprocess_matches (char ***matchesp, int matching_filenames) { char *t, **matches, **temp_matches; int nmatch, i; @@ -1537,7 +1509,7 @@ postprocess_matches (matchesp, matching_filenames) } static int -complete_get_screenwidth () +complete_get_screenwidth (void) { int cols; char *envcols; @@ -1558,9 +1530,7 @@ complete_get_screenwidth () of strings, in argv format, LEN is the number of strings in MATCHES, and MAX is the length of the longest string in MATCHES. */ void -rl_display_match_list (matches, len, max) - char **matches; - int len, max; +rl_display_match_list (char **matches, int len, int max) { int count, limit, printed_len, lines, cols; int i, j, k, l, common_length, sind; @@ -1717,8 +1687,7 @@ rl_display_match_list (matches, len, max) and ask the user if he wants to see the list if there are more matches than RL_COMPLETION_QUERY_ITEMS. */ static void -display_matches (matches) - char **matches; +display_matches (char **matches) { int len, max, i; char *temp; @@ -1784,11 +1753,9 @@ display_matches (matches) rl_display_fixed = 1; } +/* qc == pointer to quoting character, if any */ static char * -make_quoted_replacement (match, mtype, qc) - char *match; - int mtype; - char *qc; /* Pointer to quoting character, if any */ +make_quoted_replacement (char *match, int mtype, char *qc) { int should_quote, do_replace; char *replacement; @@ -1830,10 +1797,7 @@ make_quoted_replacement (match, mtype, qc) } static void -insert_match (match, start, mtype, qc) - char *match; - int start, mtype; - char *qc; +insert_match (char *match, int start, int mtype, char *qc) { char *replacement, *r; char oqc; @@ -1890,9 +1854,7 @@ insert_match (match, start, mtype, qc) value of _rl_complete_mark_symlink_dirs, but may be modified by an application's completion function). */ static int -append_to_match (text, delimiter, quote_char, nontrivial_match) - char *text; - int delimiter, quote_char, nontrivial_match; +append_to_match (char *text, int delimiter, int quote_char, int nontrivial_match) { char temp_string[4], *filename, *fn; int temp_string_index, s; @@ -1959,10 +1921,7 @@ append_to_match (text, delimiter, quote_char, nontrivial_match) } static void -insert_all_matches (matches, point, qc) - char **matches; - int point; - char *qc; +insert_all_matches (char **matches, int point, char *qc) { int i; char *rp; @@ -1998,8 +1957,7 @@ insert_all_matches (matches, point, qc) } void -_rl_free_match_list (matches) - char **matches; +_rl_free_match_list (char **matches) { register int i; @@ -2021,17 +1979,14 @@ _rl_free_match_list (matches) `@' means to do standard completion, and list all possible completions if there is more than one and partial completion is not possible. */ int -rl_complete_internal (what_to_do) - int what_to_do; +rl_complete_internal (int what_to_do) { char **matches; rl_compentry_func_t *our_func; int start, end, delimiter, found_quote, i, nontrivial_lcd; char *text, *saved_line_buffer; char quote_char; -#if 1 int tlen, mlen; -#endif RL_SETSTATE(RL_STATE_COMPLETING); @@ -2206,9 +2161,7 @@ rl_complete_internal (what_to_do) when there are no more matches. */ char ** -rl_completion_matches (text, entry_function) - const char *text; - rl_compentry_func_t *entry_function; +rl_completion_matches (const char *text, rl_compentry_func_t *entry_function) { register int i; @@ -2276,9 +2229,7 @@ rl_completion_matches (text, entry_function) TEXT contains a partial username preceded by a random character (usually `~'). */ char * -rl_username_completion_function (text, state) - const char *text; - int state; +rl_username_completion_function (const char *text, int state) { #if defined (__WIN32__) || defined (__OPENNT) return (char *)NULL; @@ -2340,11 +2291,7 @@ rl_username_completion_function (text, state) _rl_completion_case_map is set, make `-' and `_' equivalent. CONVFN is the possibly-converted directory entry; FILENAME is what the user typed. */ static int -complete_fncmp (convfn, convlen, filename, filename_len) - const char *convfn; - int convlen; - const char *filename; - int filename_len; +complete_fncmp (const char *convfn, int convlen, const char *filename, int filename_len) { register char *s1, *s2; int d, len; @@ -2472,9 +2419,7 @@ complete_fncmp (convfn, convlen, filename, filename_len) because of all the pathnames that must be followed when looking up the completion for a command. */ char * -rl_filename_completion_function (text, state) - const char *text; - int state; +rl_filename_completion_function (const char *text, int state) { static DIR *directory = (DIR *)NULL; static char *filename = (char *)NULL; @@ -2702,8 +2647,7 @@ rl_filename_completion_function (text, state) hit the end of the match list, we restore the original unmatched text, ring the bell, and reset the counter to zero. */ int -rl_old_menu_complete (count, invoking_key) - int count, invoking_key; +rl_old_menu_complete (int count, int invoking_key) { rl_compentry_func_t *our_func; int matching_filenames, found_quote; @@ -2824,9 +2768,17 @@ rl_old_menu_complete (count, invoking_key) return (0); } +/* The current version of menu completion. + The differences between this function and the original are: + +1. It honors the maximum number of completions variable (completion-query-items) +2. It appends to the word as usual if there is only one match +3. It displays the common prefix if there is one, and makes it the first menu + choice if the menu-complete-display-prefix option is enabled +*/ + int -rl_menu_complete (count, ignore) - int count, ignore; +rl_menu_complete (int count, int ignore) { rl_compentry_func_t *our_func; int matching_filenames, found_quote; @@ -2998,8 +2950,7 @@ rl_menu_complete (count, ignore) } int -rl_backward_menu_complete (count, key) - int count, key; +rl_backward_menu_complete (int count, int key) { /* Positive arguments to backward-menu-complete translate into negative arguments for menu-complete, and vice versa. */ diff --git a/lib/readline/display.c b/lib/readline/display.c index 2d2e768a..75019efc 100644 --- a/lib/readline/display.c +++ b/lib/readline/display.c @@ -1,6 +1,6 @@ /* display.c -- readline redisplay facility. */ -/* Copyright (C) 1987-2015 Free Software Foundation, Inc. +/* Copyright (C) 1987-2017 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. @@ -124,7 +124,6 @@ static int _rl_col_width PARAMS((const char *, int, int, int)); #define PROMPT_ENDING_INDEX \ ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) ? prompt_physical_chars : prompt_last_invisible+1) - /* **************************************************************** */ /* */ /* Display stuff */ @@ -159,9 +158,6 @@ rl_voidfunc_t *rl_redisplay_function = rl_redisplay; /* What YOU turn on when you have handled all redisplay yourself. */ int rl_display_fixed = 0; -int _rl_suppress_redisplay = 0; -int _rl_want_redisplay = 0; - /* The stuff that gets printed out before the actual text of the line. This is usually pointing to rl_prompt. */ char *rl_display_prompt = (char *)NULL; @@ -178,6 +174,10 @@ int _rl_vi_cmd_modestr_len; /* Pseudo-global variables declared here. */ +/* Hints for other parts of readline to give to the display engine. */ +int _rl_suppress_redisplay = 0; +int _rl_want_redisplay = 0; + /* The visible cursor position. If you print some text, adjust this. */ /* NOTE: _rl_last_c_pos is used as a buffer index when not in a locale supporting multibyte characters, and an absolute cursor position when @@ -186,14 +186,24 @@ int _rl_vi_cmd_modestr_len; int _rl_last_c_pos = 0; int _rl_last_v_pos = 0; +/* Number of physical lines consumed by the current line buffer currently + on screen minus 1. */ +int _rl_vis_botlin = 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 + adjustment itself. */ static int cpos_adjusted; + +/* The index into the line buffer corresponding to the cursor position */ static int cpos_buffer_position; + +/* A flag to note when we're displaying the first line of the prompt */ static int displaying_prompt_first_line; +/* The number of multibyte characters in the prompt, if any */ static int prompt_multibyte_chars; -/* Number of lines currently on screen minus 1. */ -int _rl_vis_botlin = 0; - static int _rl_inv_botlin = 0; /* Variables used only in this file. */ @@ -216,7 +226,11 @@ static int line_size = 1024; static char *local_prompt, *local_prompt_prefix; static int local_prompt_len; -static int prompt_visible_length, prompt_prefix_length; +static int prompt_prefix_length; +/* Number of chars in the buffer that contribute to visible chars on the screen. + This might be different from the number of physical chars in the presence + of multibyte characters */ +static int prompt_visible_length; /* The number of invisible characters in the line currently being displayed on the screen. */ @@ -242,16 +256,26 @@ static int prompt_last_screen_line; static int prompt_physical_chars; +/* An array of indexes into the prompt string where we will break physical + screen lines. It's easier to compute in expand_prompt and use later in + rl_redisplay instead of having rl_redisplay try to guess about invisible + characters in the prompt or use heuristics about where they are. */ +static int *local_prompt_newlines; + /* set to a non-zero value by rl_redisplay if we are marking modified history lines and the current line is so marked. */ static int modmark; +static int line_totbytes; + /* Variables to save and restore prompt and display information. */ /* These are getting numerous enough that it's time to create a struct. */ static char *saved_local_prompt; static char *saved_local_prefix; +static int *saved_local_prompt_newlines; + static int saved_last_invisible; static int saved_visible_length; static int saved_prefix_length; @@ -262,8 +286,7 @@ static int saved_physical_chars; /* Return a string indicating the editing mode, for use in the prompt. */ static char * -prompt_modestr (lenp) - int *lenp; +prompt_modestr (int *lenp) { if (rl_editing_mode == emacs_mode) { @@ -291,7 +314,8 @@ prompt_modestr (lenp) index of the last invisible character in the returned string. NIFLP, if non-zero, is a place to store the number of invisible characters in the first prompt line. The previous are used as byte counts -- indexes - into a character buffer. */ + into a character buffer. *VLP gets the number of physical characters in + the expanded prompt (visible length) */ /* Current implementation: \001 (^A) start non-visible characters @@ -304,15 +328,16 @@ prompt_modestr (lenp) PMT_MULTILINE caller indicates that this is part of a multiline prompt */ +/* This approximates the number of lines the prompt will take when displayed */ +#define APPROX_DIV(n, d) (((n) < (d)) ? 1 : ((n) / (d)) + 1) + static char * -expand_prompt (pmt, flags, lp, lip, niflp, vlp) - char *pmt; - int flags; - int *lp, *lip, *niflp, *vlp; +expand_prompt (char *pmt, int flags, int *lp, int *lip, int *niflp, int *vlp) { char *r, *ret, *p, *igstart, *nprompt, *ms; int l, rl, last, ignoring, ninvis, invfl, invflset, ind, pind, physchars; - int mlen; + int mlen, newlines, newlines_guess, bound; + int mb_cur_max; /* We only expand the mode string for the last line of a multiline prompt (a prompt with embedded newlines). */ @@ -327,29 +352,54 @@ expand_prompt (pmt, flags, lp, lip, niflp, vlp) else nprompt = pmt; - /* Short-circuit if we can. */ - if ((MB_CUR_MAX <= 1 || rl_byte_oriented) && strchr (nprompt, RL_PROMPT_START_IGNORE) == 0) + mb_cur_max = MB_CUR_MAX; + + if (_rl_screenwidth == 0) + _rl_get_screen_size (0, 0); /* avoid division by zero */ + + /* Short-circuit if we can. We can do this if we are treating the prompt as + a sequence of bytes and there are no invisible characters in the prompt + to deal with. Since we populate local_prompt_newlines, we have to run + through the rest of the function if this prompt looks like it's going to + be longer than one screen line. */ + if ((mb_cur_max <= 1 || rl_byte_oriented) && strchr (nprompt, RL_PROMPT_START_IGNORE) == 0) { - r = (nprompt == pmt) ? savestring (pmt) : nprompt; + l = strlen (nprompt); + if (l < (_rl_screenwidth > 0 ? _rl_screenwidth : 80)) + { + r = (nprompt == pmt) ? savestring (pmt) : nprompt; + if (lp) + *lp = l; + if (lip) + *lip = 0; + if (niflp) + *niflp = 0; + if (vlp) + *vlp = l; + + local_prompt_newlines = (int *) xrealloc (local_prompt_newlines, sizeof (int) * 2); + local_prompt_newlines[0] = 0; + local_prompt_newlines[1] = -1; - if (lp) - *lp = strlen (r); - if (lip) - *lip = 0; - if (niflp) - *niflp = 0; - if (vlp) - *vlp = lp ? *lp : strlen (r); - return r; + return r; + } } l = strlen (nprompt); /* XXX */ r = ret = (char *)xmalloc (l + 1); + /* Guess at how many screen lines the prompt will take to size the array that + keeps track of where the line wraps happen */ + newlines_guess = (_rl_screenwidth > 0) ? APPROX_DIV(l, _rl_screenwidth) : APPROX_DIV(l, 80); + local_prompt_newlines = (int *) xrealloc (local_prompt_newlines, sizeof (int) * (newlines_guess + 1)); + local_prompt_newlines[newlines = 0] = 0; + for (rl = 1; rl <= newlines_guess; rl++) + local_prompt_newlines[rl] = -1; + rl = physchars = 0; /* mode string now part of nprompt */ - invfl = 0; /* invisible chars in first line of prompt */ - invflset = 0; /* we only want to set invfl once */ - igstart = 0; + invfl = 0; /* invisible chars in first line of prompt */ + invflset = 0; /* we only want to set invfl once */ + igstart = 0; /* we're not ignoring any characters yet */ for (ignoring = last = ninvis = 0, p = nprompt; p && *p; p++) { @@ -371,7 +421,7 @@ expand_prompt (pmt, flags, lp, lip, niflp, vlp) else { #if defined (HANDLE_MULTIBYTE) - if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + if (mb_cur_max > 1 && rl_byte_oriented == 0) { pind = p - nprompt; ind = _rl_find_next_mbchar (nprompt, pind, 1, MB_FIND_NONZERO); @@ -405,11 +455,29 @@ expand_prompt (pmt, flags, lp, lip, niflp, vlp) ninvis++; /* invisible chars byte counter */ } - if (invflset == 0 && rl >= _rl_screenwidth) + if (invflset == 0 && physchars >= _rl_screenwidth) { invfl = ninvis; invflset = 1; } + + if (physchars >= (bound = (newlines + 1) * _rl_screenwidth) && local_prompt_newlines[newlines+1] == -1) + { + int new; + if (physchars > bound) /* should rarely happen */ + { +#if defined (HANDLE_MULTIBYTE) + *r = '\0'; /* need null-termination for strlen */ + if (mb_cur_max > 1 && rl_byte_oriented == 0) + new = _rl_find_prev_mbchar (ret, r - ret, MB_FIND_ANY); + else +#endif + new = r - ret - (physchars - bound); /* XXX */ + } + else + new = r - ret; + local_prompt_newlines[++newlines] = new; + } } } @@ -435,8 +503,7 @@ expand_prompt (pmt, flags, lp, lip, niflp, vlp) /* Just strip out RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE from PMT and return the rest of PMT. */ char * -_rl_strip_prompt (pmt) - char *pmt; +_rl_strip_prompt (char *pmt) { char *ret; @@ -445,7 +512,7 @@ _rl_strip_prompt (pmt) } void -_rl_reset_prompt () +_rl_reset_prompt (void) { rl_visible_prompt_length = rl_expand_prompt (rl_prompt); } @@ -461,15 +528,20 @@ _rl_reset_prompt () * prompt_visible_length = number of visible characters in local_prompt * prompt_prefix_length = number of visible characters in local_prompt_prefix * + * It also tries to keep track of the number of invisible characters in the + * prompt string, and where they are. + * * This function is called once per call to readline(). It may also be * called arbitrarily to expand the primary prompt. * * The return value is the number of visible characters on the last line - * of the (possibly multi-line) prompt. + * of the (possibly multi-line) prompt. In this case, multi-line means + * there are embedded newlines in the prompt string itself, not that the + * number of physical characters exceeds the screen width and the prompt + * wraps. */ int -rl_expand_prompt (prompt) - char *prompt; +rl_expand_prompt (char *prompt) { char *p, *t; int c; @@ -527,8 +599,7 @@ rl_expand_prompt (prompt) increased. If the lines have already been allocated, this ensures that they can hold at least MINSIZE characters. */ static void -init_line_structures (minsize) - int minsize; +init_line_structures (int minsize) { register int n; @@ -575,9 +646,9 @@ init_line_structures (minsize) line_structures_initialized = 1; } -/* Basic redisplay algorithm. */ +/* Basic redisplay algorithm. See comments inline. */ void -rl_redisplay () +rl_redisplay (void) { register int in, out, c, linenum, cursor_linenum; register char *line; @@ -638,6 +709,10 @@ rl_redisplay () 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. */ + /* 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 + any case */ if (rl_display_prompt == rl_prompt || local_prompt) { if (local_prompt_prefix && forced_display) @@ -692,6 +767,21 @@ rl_redisplay () wrap_offset = prompt_invis_chars_first_line = 0; } +#if defined (HANDLE_MULTIBYTE) +#define CHECK_INV_LBREAKS() \ + do { \ + if (newlines >= (inv_lbsize - 2)) \ + { \ + inv_lbsize *= 2; \ + inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \ + } \ + if (newlines >= (line_state_invisible->wbsize - 2)) \ + { \ + line_state_invisible->wbsize *= 2; \ + line_state_invisible->wrapped_line = (int *)xrealloc (line_state_invisible->wrapped_line, line_state_invisible->wbsize * sizeof(int)); \ + } \ + } while (0) +#else #define CHECK_INV_LBREAKS() \ do { \ if (newlines >= (inv_lbsize - 2)) \ @@ -700,6 +790,7 @@ rl_redisplay () inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \ } \ } while (0) +#endif /* !HANDLE_MULTIBYTE */ #if defined (HANDLE_MULTIBYTE) #define CHECK_LPOS() \ @@ -713,7 +804,7 @@ rl_redisplay () inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \ } \ inv_lbreaks[++newlines] = out; \ - if (newlines >= (line_state_invisible->wbsize - 1)) \ + if (newlines >= (line_state_invisible->wbsize - 2)) \ { \ line_state_invisible->wbsize *= 2; \ line_state_invisible->wrapped_line = (int *)xrealloc (line_state_invisible->wrapped_line, line_state_invisible->wbsize * sizeof(int)); \ @@ -742,7 +833,10 @@ rl_redisplay () /* inv_lbreaks[i] is where line i starts in the buffer. */ inv_lbreaks[newlines = 0] = 0; /* lpos is a physical cursor position, so it needs to be adjusted by the - number of invisible characters in the prompt, per line */ + number of invisible characters in the prompt, per line. We compute + the line breaks in the prompt string in expand_prompt, taking invisible + characters into account, and if lpos exceeds the screen width, we copy + the data in the loop below. */ lpos = prompt_physical_chars + modmark; #if defined (HANDLE_MULTIBYTE) @@ -752,92 +846,38 @@ rl_redisplay () /* prompt_invis_chars_first_line is the number of invisible characters in the first physical line of the prompt. - wrap_offset - prompt_invis_chars_first_line is the number of invis - chars on the second (or, more generally, last) line. */ + wrap_offset - prompt_invis_chars_first_line is usually the number of + invis chars on the second (or, more generally, last) line. */ /* This is zero-based, used to set the newlines */ prompt_lines_estimate = lpos / _rl_screenwidth; /* what if lpos is already >= _rl_screenwidth before we start drawing the contents of the command line? */ - while (lpos >= _rl_screenwidth) - { - int z, p; - int nocorrect, wadjust; - - nocorrect = 0; - /* Adjust depending on the invisible characters in the line. We use a - heuristic based on experience: invisible characters nearly always - appear in the first and last lines of the prompt */ - wadjust = (newlines == 0) - ? prompt_invis_chars_first_line - : ((newlines == prompt_lines_estimate) - ? (wrap_offset - prompt_invis_chars_first_line) - : 0); - - /* fix from Darin Johnson <darin@acuson.com> for prompt string with - invisible characters that is longer than the screen width. The - prompt_invis_chars_first_line variable could be made into an array - saying how many invisible characters there are per line, but that's - probably too much work for the benefit gained. How many people have - prompts that exceed two physical lines? - Additional logic fix from Edward Catmur <ed@catmur.co.uk> */ -#if defined (HANDLE_MULTIBYTE) - if (mb_cur_max > 1 && rl_byte_oriented == 0 && prompt_multibyte_chars > 0) - { - nocorrect = 1; - n0 = num; - temp = local_prompt_len; - while (num < temp) - { - /* This has to take invisible characters in the prompt into - account. */ - z = _rl_col_width (local_prompt, n0, num, 1) - wadjust; - if (z > _rl_screenwidth) - { - num = _rl_find_prev_mbchar (local_prompt, num, MB_FIND_ANY); - break; - } - else if (z == _rl_screenwidth) - { - /* If we are in the middle or at the end of a multibyte - character, we want to move to the start, then find out - where it ends so we know where to insert the newline. - If this isn't a multibyte character, its the same as num++ */ - p = _rl_find_prev_mbchar (local_prompt, num, MB_FIND_ANY); - num = _rl_find_next_mbchar (local_prompt, p, 1, MB_FIND_ANY); - break; - } - num++; - } - temp = num; - } - else -#endif /* !HANDLE_MULTIBYTE */ - temp = ((newlines + 1) * _rl_screenwidth); + if (lpos >= _rl_screenwidth) + { + temp = 0; - /* Now account for invisible characters in the current line. */ - /* XXX - this assumes that the invisible characters may be split, but only - between the first and the last lines. */ - if (nocorrect == 0) - temp += wadjust; + /* first copy the linebreaks array we computed in expand_prompt */ + while (local_prompt_newlines[newlines+1] != -1) + { + temp = local_prompt_newlines[newlines+1]; + inv_lbreaks[++newlines] = temp; + } - inv_lbreaks[++newlines] = temp; -#if defined (HANDLE_MULTIBYTE) - /* lpos is a physical cursor position, so it needs to take the invisible - characters into account. */ + /* Now set lpos from the last newline */ if (mb_cur_max > 1 && rl_byte_oriented == 0 && prompt_multibyte_chars > 0) - lpos -= _rl_col_width (local_prompt, n0, num, 1) - wadjust; + lpos = _rl_col_width (local_prompt, temp, local_prompt_len, 1) - (wrap_offset - prompt_invis_chars_first_line); else -#endif - lpos -= _rl_screenwidth; /* all physical cursor positions */ + lpos -= (_rl_screenwidth * newlines); } prompt_last_screen_line = newlines; /* Draw the rest of the line (after the prompt) into invisible_line, keeping - track of where the cursor is (cpos_buffer_position), the number of the line containing - the cursor (lb_linenum), the last line number (lb_botlin and inv_botlin). + track of where the cursor is (cpos_buffer_position), the number of the + line containing the cursor (lb_linenum), the last line number (lb_botlin + and inv_botlin). It maintains an array of line breaks for display (inv_lbreaks). This handles expanding tabs for display and displaying meta characters. */ lb_linenum = 0; @@ -846,8 +886,13 @@ rl_redisplay () if (mb_cur_max > 1 && rl_byte_oriented == 0) { memset (&ps, 0, sizeof (mbstate_t)); - /* XXX - what if wc_bytes ends up <= 0? check for MB_INVALIDCH */ - wc_bytes = mbrtowc (&wc, rl_line_buffer, rl_end, &ps); + if (_rl_utf8locale && UTF8_SINGLEBYTE(rl_line_buffer[0])) + { + wc = (wchar_t)rl_line_buffer[0]; + wc_bytes = 1; + } + else + wc_bytes = mbrtowc (&wc, rl_line_buffer, rl_end, &ps); } else wc_bytes = 1; @@ -909,6 +954,9 @@ rl_redisplay () temp = _rl_screenwidth - lpos; CHECK_INV_LBREAKS (); inv_lbreaks[++newlines] = out + temp; +#if defined (HANDLE_MULTIBYTE) + line_state_invisible->wrapped_line[newlines] = _rl_wrapped_multicolumn; +#endif lpos = 4 - temp; } else @@ -939,6 +987,9 @@ rl_redisplay () temp2 = _rl_screenwidth - lpos; CHECK_INV_LBREAKS (); inv_lbreaks[++newlines] = out + temp2; +#if defined (HANDLE_MULTIBYTE) + line_state_invisible->wrapped_line[newlines] = _rl_wrapped_multicolumn; +#endif lpos = temp - temp2; while (out < newout) line[out++] = ' '; @@ -956,6 +1007,9 @@ rl_redisplay () line[out++] = '\0'; /* XXX - sentinel */ CHECK_INV_LBREAKS (); inv_lbreaks[++newlines] = out; +#if defined (HANDLE_MULTIBYTE) + line_state_invisible->wrapped_line[newlines] = _rl_wrapped_multicolumn; +#endif lpos = 0; } else if (CTRL_CHAR (c) || c == RUBOUT) @@ -1007,15 +1061,21 @@ rl_redisplay () if (mb_cur_max > 1 && rl_byte_oriented == 0) { in += wc_bytes; - /* XXX - what if wc_bytes ends up <= 0? check for MB_INVALIDCH */ - wc_bytes = mbrtowc (&wc, rl_line_buffer + in, rl_end - in, &ps); + if (_rl_utf8locale && UTF8_SINGLEBYTE(rl_line_buffer[in])) + { + wc = (wchar_t)rl_line_buffer[in]; + wc_bytes = 1; + memset (&ps, 0, sizeof (mbstate_t)); /* re-init state */ + } + else + wc_bytes = mbrtowc (&wc, rl_line_buffer + in, rl_end - in, &ps); } else in++; #endif - } line[out] = '\0'; + line_totbytes = out; if (cpos_buffer_position < 0) { cpos_buffer_position = out; @@ -1025,6 +1085,10 @@ rl_redisplay () inv_botlin = lb_botlin = _rl_inv_botlin = newlines; CHECK_INV_LBREAKS (); inv_lbreaks[newlines+1] = out; +#if defined (HANDLE_MULTIBYTE) + /* This should be 0 anyway */ + line_state_invisible->wrapped_line[newlines+1] = _rl_wrapped_multicolumn; +#endif cursor_linenum = lb_linenum; /* CPOS_BUFFER_POSITION == position in buffer where cursor should be placed. @@ -1092,8 +1156,8 @@ rl_redisplay () /* update_line potentially changes _rl_last_c_pos, but doesn't take invisible characters into account, since _rl_last_c_pos - is an absolute cursor position in a multibyte locale. See - if compensating here is the right thing, or if we have to + is an absolute cursor position in a multibyte locale. We + choose to (mostly) compensate for that here, rather than change update_line itself. There are several cases in which update_line adjusts _rl_last_c_pos itself (so it can pass _rl_move_cursor_relative accurate values); it communicates @@ -1104,11 +1168,16 @@ rl_redisplay () wrap_offset. */ if (linenum == 0 && (mb_cur_max > 1 && rl_byte_oriented == 0) && OLD_CPOS_IN_PROMPT()) _rl_last_c_pos -= prompt_invis_chars_first_line; /* XXX - was wrap_offset */ - else if (linenum == prompt_last_screen_line && prompt_physical_chars > _rl_screenwidth && + else if (cpos_adjusted == 0 && + linenum == prompt_last_screen_line && + prompt_physical_chars > _rl_screenwidth && (mb_cur_max > 1 && rl_byte_oriented == 0) && - cpos_adjusted == 0 && _rl_last_c_pos != o_cpos && - _rl_last_c_pos > (prompt_last_invisible - _rl_screenwidth - prompt_invis_chars_first_line)) + _rl_last_c_pos > (prompt_last_invisible - _rl_screenwidth - prompt_invis_chars_first_line)) /* XXX - rethink this last one */ + /* This assumes that all the invisible characters are split + between the first and last lines of the prompt, if the + prompt consumes more than two lines. It's usually right */ + /* XXX - not sure this is ever executed */ _rl_last_c_pos -= (wrap_offset-prompt_invis_chars_first_line); /* If this is the line with the prompt, we might need to @@ -1178,6 +1247,9 @@ rl_redisplay () _rl_last_c_pos += wrap_offset; } + /* Now we move the cursor to where it needs to be. First, make + sure we are on the correct line (cursor_linenum). */ + /* We have to reprint the prompt if it contains invisible characters, since it's not generally OK to just reprint the characters from the current cursor position. But we @@ -1219,9 +1291,10 @@ rl_redisplay () position that doesn't take invisible characters in the prompt into account. We use a fudge factor to compensate. */ - /* Since _rl_backspace() doesn't know about invisible characters in the - prompt, and there's no good way to tell it, we compensate for - those characters here and call _rl_backspace() directly. */ + /* Since _rl_backspace() doesn't know about invisible characters in + the prompt, and there's no good way to tell it, we compensate for + those characters here and call _rl_backspace() directly if + necessary */ if (wrap_offset && cursor_linenum == 0 && nleft < _rl_last_c_pos) { /* TX == new physical cursor position in multibyte locale. */ @@ -1246,7 +1319,7 @@ rl_redisplay () _rl_move_cursor_relative (nleft, &invisible_line[pos]); } } - else /* Do horizontal scrolling. */ + else /* Do horizontal scrolling. Much simpler */ { #define M_OFFSET(margin, offset) ((margin) == 0 ? offset : 0) int lmargin, ndisp, nleft, phys_c_pos, t; @@ -1306,7 +1379,7 @@ rl_redisplay () right edge of the screen. If LMARGIN is 0, we need to take the wrap offset into account. */ t = lmargin + M_OFFSET (lmargin, wrap_offset) + _rl_screenwidth; - if (t < out) + if (t > 0 && t < out) line[t - 1] = '>'; if (rl_display_fixed == 0 || forced_display || lmargin != last_lmargin) @@ -1384,9 +1457,7 @@ 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 (old, new, current_line, omax, nmax, inv_botlin) - register char *old, *new; - int current_line, omax, nmax, inv_botlin; +update_line (char *old, char *new, int current_line, int omax, int nmax, int inv_botlin) { register char *ofd, *ols, *oe, *nfd, *nls, *ne; int temp, lendiff, wsatend, od, nd, twidth, o_cpos; @@ -1411,52 +1482,145 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) if (temp == _rl_screenwidth && _rl_term_autowrap && !_rl_horizontal_scroll_mode && _rl_last_v_pos == current_line - 1) { + /* We're going to wrap around by writing the first character of NEW to + the screen and dealing with changes to what's visible by modifying + OLD to match it. Complicated by the presence of multi-width + characters at the end of the line or beginning of the new one. */ + /* old is always somewhere in visible_line; new is always somewhere in + invisible_line. These should always be null-terminated. */ #if defined (HANDLE_MULTIBYTE) if (mb_cur_max > 1 && rl_byte_oriented == 0) { wchar_t wc; mbstate_t ps; - int tempwidth, bytes; + int oldwidth, newwidth; + int oldbytes, newbytes; size_t ret; /* This fixes only double-column characters, but if the wrapped character consumes more than three columns, spaces will be inserted in the string buffer. */ - if (current_line < line_state_visible->wbsize && line_state_visible->wrapped_line[current_line] > 0) - _rl_clear_to_eol (line_state_visible->wrapped_line[current_line]); + /* XXX remember that we are working on the invisible line right now; + we don't swap visible and invisible until just before rl_redisplay + returns */ + /* This will remove the extra placeholder space we added with + _rl_wrapped_multicolumn */ + if (current_line < line_state_invisible->wbsize && line_state_invisible->wrapped_line[current_line] > 0) + _rl_clear_to_eol (line_state_invisible->wrapped_line[current_line]); + + /* 1. how many screen positions does first char in old consume? */ + memset (&ps, 0, sizeof (mbstate_t)); + ret = mbrtowc (&wc, old, mb_cur_max, &ps); + oldbytes = ret; + if (MB_INVALIDCH (ret)) + { + oldwidth = 1; + oldbytes = 1; + } + else if (MB_NULLWCH (ret)) + oldwidth = 0; + else + oldwidth = WCWIDTH (wc); + if (oldwidth < 0) + oldwidth = 1; + /* 2. how many screen positions does the first char in new consume? */ memset (&ps, 0, sizeof (mbstate_t)); ret = mbrtowc (&wc, new, mb_cur_max, &ps); + newbytes = ret; if (MB_INVALIDCH (ret)) { - tempwidth = 1; - ret = 1; + newwidth = 1; + newbytes = 1; } else if (MB_NULLWCH (ret)) - tempwidth = 0; + newwidth = 0; else - tempwidth = WCWIDTH (wc); + newwidth = WCWIDTH (wc); + if (newwidth < 0) + newwidth = 1; + + /* 3. if the new width is less than the old width, we need to keep + going in new until we have consumed at least that many screen + positions, and figure out how many bytes that will take */ + while (newbytes < nmax && newwidth < oldwidth) + { + int t; - if (tempwidth > 0) + ret = mbrtowc (&wc, new+newbytes, mb_cur_max, &ps); + if (MB_INVALIDCH (ret)) + { + newwidth += 1; + newbytes += 1; + } + else if (MB_NULLWCH (ret)) + break; + else + { + t = WCWIDTH (wc); + newwidth += (t >= 0) ? t : 1; + newbytes += ret; + } + } + /* 4. If the new width is more than the old width, keep going in old + until we have consumed exactly that many screen positions, and + figure out how many bytes that will take. This is an optimization */ + while (oldbytes < omax && oldwidth < newwidth) { - int count, i; - bytes = ret; - for (count = 0; count < bytes; count++) - putc (new[count], rl_outstream); - _rl_last_c_pos = tempwidth; + int t; + + ret = mbrtowc (&wc, old+oldbytes, mb_cur_max, &ps); + if (MB_INVALIDCH (ret)) + { + oldwidth += 1; + oldbytes += 1; + } + else if (MB_NULLWCH (ret)) + break; + else + { + t = WCWIDTH (wc); + oldwidth += (t >= 0) ? t : 1; + oldbytes += ret; + } + } + /* 5. write the first newbytes of new, which takes newwidth. This is + where the screen wrapping takes place, and we are now writing + characters onto the new line. We need to fix up old so it + accurately reflects what is on the screen after the + _rl_output_some_chars below. */ + if (newwidth > 0) + { + int count, i, j; + char *optr; + + _rl_output_some_chars (new, newbytes); + _rl_last_c_pos = newwidth; _rl_last_v_pos++; - memset (&ps, 0, sizeof (mbstate_t)); - ret = mbrtowc (&wc, old, mb_cur_max, &ps); - if (ret != 0 && bytes != 0) + + /* 5a. If the number of screen positions doesn't match, punt + and do a dumb update. */ + if (newwidth != oldwidth) + { + ne = new + nmax; + nd = newbytes; + nfd = new + nd; + goto dumb_update; + } + if (oldbytes != 0 && newbytes != 0) { - if (MB_INVALIDCH (ret)) - ret = 1; - memmove (old+bytes, old+ret, strlen (old+ret)); - memcpy (old, new, bytes); + /* We have written as many bytes from new as we need to + 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); + memcpy (old, new, newbytes); + j = newbytes - oldbytes; + + omax += j; /* Fix up indices if we copy data from one line to another */ - omax += bytes - ret; for (i = current_line+1; i <= inv_botlin+1; i++) - vis_lbreaks[i] += bytes - ret; + vis_lbreaks[i] += j; } } else @@ -1482,7 +1646,6 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) } } - /* Find first difference. */ #if defined (HANDLE_MULTIBYTE) if (mb_cur_max > 1 && rl_byte_oriented == 0) @@ -1501,6 +1664,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) memset (&ps_new, 0, sizeof(mbstate_t)); memset (&ps_old, 0, sizeof(mbstate_t)); + /* Are the old and new lines the same? */ if (omax == nmax && STREQN (new, old, omax)) { old_offset = omax; @@ -1510,6 +1674,8 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) } else { + /* Go through the line from the beginning and find the first + difference. */ new_offset = old_offset = 0; for (ofd = old, nfd = new; (ofd - old < omax) && *ofd && @@ -1565,6 +1731,8 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) wsatend = 1; /* flag for trailing whitespace */ #if defined (HANDLE_MULTIBYTE) + /* Find the last character that is the same between the two lines. This + bounds the region that needs to change. */ if (mb_cur_max > 1 && rl_byte_oriented == 0) { ols = old + _rl_find_prev_mbchar (old, oe - old, MB_FIND_ANY); @@ -1724,12 +1892,29 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) nd = lendiff; /* Do a dumb update and return */ +dumb_update: temp = ne - nfd; if (temp > 0) { _rl_output_some_chars (nfd, temp); if (mb_cur_max > 1 && rl_byte_oriented == 0) - _rl_last_c_pos += _rl_col_width (new, nd, ne - new, 1); + { + _rl_last_c_pos += _rl_col_width (new, nd, ne - new, 1); + /* Need to adjust here based on wrap_offset. Guess that if + this is the line containing the last line of the prompt + we need to adjust by + wrap_offset-prompt_invis_chars_first_line + on the assumption that this is the number of invisible + characters in the last line of the prompt. */ + if (wrap_offset > prompt_invis_chars_first_line && + 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; + } + } else _rl_last_c_pos += temp; } @@ -1804,6 +1989,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) { /* Non-zero if we're increasing the number of lines. */ int gl = current_line >= _rl_vis_botlin && inv_botlin > _rl_vis_botlin; + /* If col_lendiff is > 0, implying that the new string takes up more screen real estate than the old, but lendiff is < 0, meaning that it takes fewer bytes, we need to just output the characters starting @@ -1819,7 +2005,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) 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; + _rl_last_c_pos -= wrap_offset; /* XXX - prompt_invis_chars_first_line? */ cpos_adjusted = 1; } return; @@ -1872,7 +2058,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) 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; + _rl_last_c_pos -= wrap_offset; /* XXX - prompt_invis_chars_first_line? */ cpos_adjusted = 1; } return; @@ -1885,7 +2071,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) 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; + _rl_last_c_pos -= wrap_offset; /* XXX - prompt_invis_chars_first_line? */ cpos_adjusted = 1; } } @@ -1952,12 +2138,26 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) _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 && + _rl_last_c_pos >= wrap_offset && /* XXX was > */ ((nfd - new) <= prompt_last_invisible)) { - _rl_last_c_pos -= wrap_offset; + _rl_last_c_pos -= wrap_offset; /* XXX - prompt_invis_chars_first_line? */ cpos_adjusted = 1; } + +#if 1 +#ifdef HANDLE_MULTIBYTE + /* If we write a non-space into the last screen column, + remove the note that we added a space to compensate for + a multibyte double-width character that didn't fit, since + it's only valid for what was previously there. */ + /* XXX - watch this */ + if (_rl_last_c_pos == _rl_screenwidth && + line_state_invisible->wrapped_line[current_line+1] && + nfd[bytes_to_insert-1] != ' ') + line_state_invisible->wrapped_line[current_line+1] = 0; +#endif +#endif } else _rl_last_c_pos += bytes_to_insert; @@ -1989,7 +2189,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) _rl_last_c_pos > wrap_offset && ((nfd - new) <= prompt_last_invisible)) { - _rl_last_c_pos -= wrap_offset; + _rl_last_c_pos -= wrap_offset; /* XXX - prompt_invis_chars_first_line? */ cpos_adjusted = 1; } } @@ -2019,7 +2219,7 @@ clear_rest_of_line: /* Tell the update routines that we have moved onto a new (empty) line. */ int -rl_on_new_line () +rl_on_new_line (void) { if (visible_line) visible_line[0] = '\0'; @@ -2035,7 +2235,7 @@ rl_on_new_line () /* Clear all screen lines occupied by the current readline line buffer (visible line) */ int -rl_clear_visible_line () +rl_clear_visible_line (void) { int curr_line; @@ -2063,9 +2263,10 @@ rl_clear_visible_line () /* Tell the update routines that we have moved onto a new line with the prompt already displayed. Code originally from the version of readline distributed with CLISP. rl_expand_prompt must have already been called - (explicitly or implicitly). This still doesn't work exactly right. */ + (explicitly or implicitly). This still doesn't work exactly right; it + should use expand_prompt() */ int -rl_on_new_line_with_prompt () +rl_on_new_line_with_prompt (void) { int prompt_size, i, l, real_screenwidth, newlines; char *prompt_last_line, *lprompt; @@ -2121,7 +2322,7 @@ rl_on_new_line_with_prompt () /* Actually update the display, period. */ int -rl_forced_update_display () +rl_forced_update_display (void) { register char *temp; @@ -2139,7 +2340,7 @@ rl_forced_update_display () /* Redraw only the last line of a multi-line prompt. */ void -rl_redraw_prompt_last_line () +rl_redraw_prompt_last_line (void) { char *t; @@ -2157,9 +2358,7 @@ rl_redraw_prompt_last_line () the movement is being done. DATA is always the visible line or the invisible line */ void -_rl_move_cursor_relative (new, data) - int new; - const char *data; +_rl_move_cursor_relative (int new, const char *data) { register int i; int woff; /* number of invisible chars on current line */ @@ -2316,8 +2515,7 @@ _rl_move_cursor_relative (new, data) /* PWP: move the cursor up or down. */ void -_rl_move_vert (to) - int to; +_rl_move_vert (int to) { register int delta, i; @@ -2357,8 +2555,7 @@ _rl_move_vert (to) /* Physically print C on rl_outstream. This is for functions which know how to optimize the display. Return the number of characters output. */ int -rl_show_char (c) - int c; +rl_show_char (int c) { int n = 1; if (META_CHAR (c) && (_rl_output_meta_chars == 0)) @@ -2385,8 +2582,7 @@ rl_show_char (c) } int -rl_character_len (c, pos) - register int c, pos; +rl_character_len (int c, int pos) { unsigned char uc; @@ -2521,7 +2717,7 @@ rl_message (format, arg1, arg2) /* How to clear things from the "echo-area". */ int -rl_clear_message () +rl_clear_message (void) { rl_display_prompt = rl_prompt; if (msg_saved_prompt) @@ -2534,7 +2730,7 @@ rl_clear_message () } int -rl_reset_line_state () +rl_reset_line_state (void) { rl_on_new_line (); @@ -2543,8 +2739,12 @@ rl_reset_line_state () return 0; } +/* Save all of the variables associated with the prompt and its display. Most + of the complexity is dealing with the invisible characters in the prompt + string and where they are. There are enough of these that I should consider + a struct. */ void -rl_save_prompt () +rl_save_prompt (void) { saved_local_prompt = local_prompt; saved_local_prefix = local_prompt_prefix; @@ -2554,22 +2754,28 @@ rl_save_prompt () saved_visible_length = prompt_visible_length; saved_invis_chars_first_line = prompt_invis_chars_first_line; saved_physical_chars = prompt_physical_chars; + saved_local_prompt_newlines = local_prompt_newlines; local_prompt = local_prompt_prefix = (char *)0; local_prompt_len = 0; + local_prompt_newlines = (int *)0; + prompt_last_invisible = prompt_visible_length = prompt_prefix_length = 0; prompt_invis_chars_first_line = prompt_physical_chars = 0; } void -rl_restore_prompt () +rl_restore_prompt (void) { FREE (local_prompt); FREE (local_prompt_prefix); + FREE (local_prompt_newlines); local_prompt = saved_local_prompt; local_prompt_prefix = saved_local_prefix; local_prompt_len = saved_local_length; + local_prompt_newlines = saved_local_prompt_newlines; + prompt_prefix_length = saved_prefix_length; prompt_last_invisible = saved_last_invisible; prompt_visible_length = saved_visible_length; @@ -2581,11 +2787,11 @@ rl_restore_prompt () saved_local_length = 0; saved_last_invisible = saved_visible_length = saved_prefix_length = 0; saved_invis_chars_first_line = saved_physical_chars = 0; + saved_local_prompt_newlines = 0; } char * -_rl_make_prompt_for_search (pchar) - int pchar; +_rl_make_prompt_for_search (int pchar) { int len; char *pmt, *p; @@ -2623,8 +2829,7 @@ _rl_make_prompt_for_search (pchar) /* Quick redisplay hack when erasing characters at the end of the line. */ void -_rl_erase_at_end_of_line (l) - int l; +_rl_erase_at_end_of_line (int l) { register int i; @@ -2638,10 +2843,10 @@ _rl_erase_at_end_of_line (l) } /* Clear to the end of the line. COUNT is the minimum - number of character spaces to clear, */ + number of character spaces to clear, but we use a terminal escape + sequence if available. */ void -_rl_clear_to_eol (count) - int count; +_rl_clear_to_eol (int count) { #ifndef __MSDOS__ if (_rl_term_clreol) @@ -2655,19 +2860,18 @@ _rl_clear_to_eol (count) /* Clear to the end of the line using spaces. COUNT is the minimum number of character spaces to clear, */ static void -space_to_eol (count) - int count; +space_to_eol (int count) { register int i; for (i = 0; i < count; i++) - putc (' ', rl_outstream); + putc (' ', rl_outstream); _rl_last_c_pos += count; } void -_rl_clear_screen () +_rl_clear_screen (void) { #ifndef __DJGPP__ if (_rl_term_clrpag) @@ -2682,9 +2886,7 @@ _rl_clear_screen () /* Insert COUNT characters from STRING to the output stream at column COL. */ static void -insert_some_chars (string, count, col) - char *string; - int count, col; +insert_some_chars (char *string, int count, int col) { open_some_spaces (col); _rl_output_some_chars (string, count); @@ -2694,8 +2896,7 @@ insert_some_chars (string, count, col) ncurses documentation and use either im/ei with explicit spaces, or IC/ic by itself. We assume there will either be ei or we don't need to use it. */ static void -open_some_spaces (col) - int col; +open_some_spaces (int col) { #if !defined (__MSDOS__) && (!defined (__MINGW32__) || defined (NCURSES_VERSION)) char *buffer; @@ -2731,8 +2932,7 @@ open_some_spaces (col) /* Delete COUNT characters from the display line. */ static void -delete_chars (count) - int count; +delete_chars (int count) { if (count > _rl_screenwidth) /* XXX */ return; @@ -2754,9 +2954,9 @@ delete_chars (count) } void -_rl_update_final () +_rl_update_final (void) { - int full_lines; + int full_lines, woff, botline_length; full_lines = 0; /* If the cursor is the only thing on an otherwise-blank last line, @@ -2768,16 +2968,23 @@ _rl_update_final () full_lines = 1; } _rl_move_vert (_rl_vis_botlin); + woff = W_OFFSET(_rl_vis_botlin, wrap_offset); + botline_length = VIS_LLEN(_rl_vis_botlin) - woff; /* If we've wrapped lines, remove the final xterm line-wrap flag. */ - if (full_lines && _rl_term_autowrap && (VIS_LLEN(_rl_vis_botlin) == _rl_screenwidth)) + if (full_lines && _rl_term_autowrap && botline_length == _rl_screenwidth) { char *last_line; - last_line = &visible_line[vis_lbreaks[_rl_vis_botlin]]; + /* 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. + This needs to be done for both calls to _rl_move_cursor_relative, + 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); */ cpos_buffer_position = -1; /* don't know where we are in buffer */ - _rl_move_cursor_relative (_rl_screenwidth - 1, last_line); /* XXX */ + _rl_move_cursor_relative (_rl_screenwidth - 1 + woff, last_line); /* XXX */ _rl_clear_to_eol (0); - putc (last_line[_rl_screenwidth - 1], rl_outstream); + putc (last_line[_rl_screenwidth - 1 + woff], rl_outstream); } _rl_vis_botlin = 0; rl_crlf (); @@ -2787,7 +2994,7 @@ _rl_update_final () /* Move to the start of the current line. */ static void -cr () +cr (void) { if (_rl_term_cr) { @@ -2804,8 +3011,7 @@ cr () terminal escape sequences. Called with the cursor at column 0 of the line to draw the prompt on. */ static void -redraw_prompt (t) - char *t; +redraw_prompt (char *t) { char *oldp; @@ -2829,7 +3035,7 @@ redraw_prompt (t) /* Redisplay the current line after a SIGWINCH is received. */ void -_rl_redisplay_after_sigwinch () +_rl_redisplay_after_sigwinch (void) { char *t; @@ -2874,7 +3080,7 @@ _rl_redisplay_after_sigwinch () } void -_rl_clean_up_for_exit () +_rl_clean_up_for_exit (void) { if (_rl_echoing_p) { @@ -2887,7 +3093,7 @@ _rl_clean_up_for_exit () } void -_rl_erase_entire_line () +_rl_erase_entire_line (void) { cr (); _rl_clear_to_eol (0); @@ -2896,7 +3102,7 @@ _rl_erase_entire_line () } void -_rl_ttyflush () +_rl_ttyflush (void) { fflush (rl_outstream); } @@ -2904,7 +3110,7 @@ _rl_ttyflush () /* return the `current display line' of the cursor -- the number of lines to move up to get to the first screen line of the current readline line. */ int -_rl_current_display_line () +_rl_current_display_line (void) { int ret, nleft; @@ -2928,9 +3134,7 @@ _rl_current_display_line () In the case of multibyte characters with stateful encoding, we have to scan from the beginning of the string to take the state into account. */ static int -_rl_col_width (str, start, end, flags) - const char *str; - int start, end, flags; +_rl_col_width (const char *str, int start, int end, int flags) { wchar_t wc; mbstate_t ps; @@ -2963,7 +3167,13 @@ _rl_col_width (str, start, end, flags) while (point < start) { - tmp = mbrlen (str + point, max, &ps); + if (_rl_utf8locale && UTF8_SINGLEBYTE(str[point])) + { + memset (&ps, 0, sizeof (mbstate_t)); + tmp = 1; + } + else + tmp = mbrlen (str + point, max, &ps); if (MB_INVALIDCH ((size_t)tmp)) { /* In this case, the bytes are invalid or too short to compose a @@ -2992,7 +3202,13 @@ _rl_col_width (str, start, end, flags) while (point < end) { - tmp = mbrtowc (&wc, str + point, max, &ps); + if (_rl_utf8locale && UTF8_SINGLEBYTE(str[point])) + { + tmp = 1; + wc = (wchar_t) str[point]; + } + else + tmp = mbrtowc (&wc, str + point, max, &ps); if (MB_INVALIDCH ((size_t)tmp)) { /* In this case, the bytes are invalid or too short to compose a diff --git a/lib/readline/doc/hstech.texi b/lib/readline/doc/hstech.texi index bba7b590..d28bd485 100644 --- a/lib/readline/doc/hstech.texi +++ b/lib/readline/doc/hstech.texi @@ -166,6 +166,9 @@ parameters managing the list itself. @deftypefun void add_history (const char *string) Place @var{string} at the end of the history list. The associated data field (if any) is set to @code{NULL}. +If the maximum number of history entries has been set using +@code{stifle_history()}, and the new number of history entries would exceed +that maximum, the oldest history entry is removed. @end deftypefun @deftypefun void add_history_time (const char *string) @@ -198,6 +201,7 @@ Clear the history list by deleting all the entries. @deftypefun void stifle_history (int max) Stifle the history list, remembering only the last @var{max} entries. +The history list will contain only @var{max} entries at a time. @end deftypefun @deftypefun int unstifle_history (void) @@ -234,10 +238,12 @@ pointer. @end deftypefun @deftypefun {HIST_ENTRY *} history_get (int offset) -Return the history entry at position @var{offset}, starting from -@code{history_base} (@pxref{History Variables}). -If there is no entry there, or if @var{offset} -is greater than the history length, return a @code{NULL} pointer. +Return the history entry at position @var{offset}. +The range of valid +values of @var{offset} starts at @code{history_base} and ends at +@var{history_length} - 1 (@pxref{History Variables}). +If there is no entry there, or if @var{offset} is outside the valid +range, return a @code{NULL} pointer. @end deftypefun @deftypefun time_t history_get_time (HIST_ENTRY *entry) diff --git a/lib/readline/doc/hsuser.texi b/lib/readline/doc/hsuser.texi index 04e192eb..d21f65d0 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--2016 Free Software Foundation, Inc. +Copyright (C) 1988--2018 Free Software Foundation, Inc. Authored by Brian Fox and Chet Ramey. Permission is granted to make and distribute verbatim copies of this manual @@ -124,7 +124,7 @@ The @code{lithist} shell option causes the shell to save the command with embedded newlines instead of semicolons. The @code{shopt} builtin is used to set these options. -@xref{Bash Builtins}, for a description of @code{shopt}. +@xref{The Shopt Builtin}, for a description of @code{shopt}. @node Bash History Builtins @section Bash History Builtins @@ -149,8 +149,8 @@ Both @var{first} and @var{last} may be specified as a string (to locate the most recent command beginning with that string) or as a number (an index into the history list, where a negative number is used as an offset from the -current command number). If @var{last} is not specified it is set to -@var{first}. If @var{first} is not specified it is set to the previous +current command number). If @var{last} is not specified, it is set to +@var{first}. If @var{first} is not specified, it is set to the previous command for editing and @minus{}16 for listing. If the @option{-l} flag is given, the commands are listed on standard output. The @option{-n} flag suppresses the command numbers when listing. The @option{-r} flag @@ -176,6 +176,7 @@ and typing @samp{r} re-executes the last command (@pxref{Aliases}). history [@var{n}] history -c history -d @var{offset} +history -d @var{start}-@var{end} history [-anrw] [@var{filename}] history -ps @var{arg} @end example @@ -198,8 +199,17 @@ with the other options to replace the history list completely. @item -d @var{offset} Delete the history entry at position @var{offset}. -@var{offset} should be specified as it appears when the history is -displayed. +If @var{offset} is positive, it should be specified as it appears when +the history is displayed. +If @var{offset} is negative, it is interpreted as relative to one greater +than the last history position, so negative indices count back from the +end of the history, and an index of @samp{-1} refers to the current +@code{history -d} command. + +@item -d @var{start}-@var{end} +Delete the history entries between positions @var{start} and @var{end}, +inclusive. Positive and negative values for @var{start} and @var{end} +are interpreted as described above. @item -a Append the new history lines to the history file. @@ -251,7 +261,9 @@ fix errors in previous commands quickly. @ifset BashFeatures History expansion is performed immediately after a complete line -is read, before the shell breaks it into words. +is read, before the shell breaks it into words, and is performed +on each line individually without taking quoting on previous lines into +account. @end ifset History expansion takes place in two parts. The first is to determine @@ -274,7 +286,7 @@ in a double-quoted string. @ifset BashFeatures Several shell options settable with the @code{shopt} -builtin (@pxref{Bash Builtins}) may be used to tailor +builtin (@pxref{The Shopt Builtin}) may be used to tailor the behavior of history expansion. If the @code{histverify} shell option is enabled, and Readline is being used, history substitutions are not immediately passed to diff --git a/lib/readline/doc/rltech.texi b/lib/readline/doc/rltech.texi index b8ce90f9..7d22b2cb 100644 --- a/lib/readline/doc/rltech.texi +++ b/lib/readline/doc/rltech.texi @@ -90,6 +90,12 @@ If @code{readline} encounters an @code{EOF} while reading the line, and the line is empty at that point, then @code{(char *)NULL} is returned. Otherwise, the line is ended just as if a newline had been typed. +Readline performs some expansion on the @var{prompt} before it is +displayed on the screen. See the description of @code{rl_expand_prompt} +(@pxref{Redisplay}) for additional details, especially if @var{prompt} +will contain characters that do not consume physical screen space when +displayed. + If you want the user to be able to get at the line later, (with @key{C-p} for example), you must call @code{add_history()} to save the line away in a @dfn{history} list of such lines. @@ -688,6 +694,11 @@ Free all storage associated with @var{keymap}. This calls @code{rl_discard_keymap} to free subordindate keymaps and macros. @end deftypefun +@deftypefun int rl_empty_keymap (Keymap keymap) +Return non-zero if there are no keys bound to functions in @var{keymap}; +zero if there are any keys bound. +@end deftypefun + Readline has several internal keymaps. These functions allow you to change which keymap is active. @@ -837,6 +848,12 @@ not @code{NULL}, the type of the object is returned in the @code{int} variable it points to (one of @code{ISFUNC}, @code{ISKMAP}, or @code{ISMACR}). @end deftypefun +@deftypefun {rl_command_func_t *} rl_function_of_keyseq_len (const char *keyseq, size_t len Keymap map, int *type) +Return the function invoked by @var{keyseq} of length @var{len} +in keymap @var{map}. Equivalent to @code{rl_function_of_keyseq} with the +addition of the @var{len} parameter. +@end deftypefun + @deftypefun {char **} rl_invoking_keyseqs (rl_command_func_t *function) Return an array of strings representing the key sequences used to invoke @var{function} in the current keymap. @@ -1679,6 +1696,19 @@ handlers, depending on the values of @code{rl_catch_signals} and @code{rl_catch_sigwinch}. @end deftypefun +If an application wants to force Readline to handle any signals that +have arrived while it has been executing, @code{rl_check_signals()} +will call Readline's internal signal handler if there are any pending +signals. This is primarily intended for those applications that use +a custom @code{rl_getc_function} (@pxref{Readline Variables}) and wish +to handle signals received while waiting for input. + +@deftypefun void rl_check_signals (void) +If there are any pending signals, call Readline's internal signal handling +functions to process them. @code{rl_pending_signal()} can be used independently +to determine whether or not there are any pending signals. +@end deftypefun + 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} diff --git a/lib/readline/doc/rluser.texi b/lib/readline/doc/rluser.texi index 4c094c88..1c9acdcc 100644 --- a/lib/readline/doc/rluser.texi +++ b/lib/readline/doc/rluser.texi @@ -524,7 +524,8 @@ set to either @samp{emacs} or @samp{vi}. @item emacs-mode-string @vindex emacs-mode-string -This string is displayed immediately before the last line of the primary +If the @var{show-mode-in-prompt} variable is enabled, +this string is displayed immediately before the last line of the primary prompt when emacs editing mode is active. The value is expanded like a key binding, so the standard set of meta- and control prefixes and backslash escape sequences is available. @@ -714,9 +715,9 @@ The default value is @samp{off}. @item show-mode-in-prompt @vindex show-mode-in-prompt -If set to @samp{on}, add a character to the beginning of the prompt +If set to @samp{on}, add a string to the beginning of the prompt indicating the editing mode: emacs, vi command, or vi insertion. -The mode strings are user-settable. +The mode strings are user-settable (e.g., @var{emacs-mode-string}). The default value is @samp{off}. @item skip-completed-text @@ -735,7 +736,8 @@ The default value is @samp{off}. @item vi-cmd-mode-string @vindex vi-cmd-mode-string -This string is displayed immediately before the last line of the primary +If the @var{show-mode-in-prompt} variable is enabled, +this string is displayed immediately before the last line of the primary prompt when vi editing mode is active and in command mode. The value is expanded like a key binding, so the standard set of meta- and control prefixes and @@ -747,7 +749,8 @@ The default is @samp{(cmd)}. @item vi-ins-mode-string @vindex vi-ins-mode-string -This string is displayed immediately before the last line of the primary +If the @var{show-mode-in-prompt} variable is enabled, +this string is displayed immediately before the last line of the primary prompt when vi editing mode is active and in insertion mode. The value is expanded like a key binding, so the standard set of meta- and control prefixes and @@ -914,8 +917,9 @@ of tests. There are four parser directives used. @item $if The @code{$if} construct allows bindings to be made based on the editing mode, the terminal being used, or the application using -Readline. The text of the test extends to the end of the line; -no characters are required to isolate it. +Readline. The text of the test, after any comparison operator, +extends to the end of the line; +unless otherwise noted, no characters are required to isolate it. @table @code @item mode @@ -935,6 +939,27 @@ the portion of the terminal name before the first @samp{-}. This allows @code{sun} to match both @code{sun} and @code{sun-cmd}, for instance. +@item version +The @code{version} test may be used to perform comparisons against +specific Readline versions. +The @code{version} expands to the current Readline version. +The set of comparison operators includes +@samp{=} (and @samp{==}), @samp{!=}, @samp{<=}, @samp{>=}, @samp{<}, +and @samp{>}. +The version number supplied on the right side of the operator consists +of a major version number, an optional decimal point, and an optional +minor version (e.g., @samp{7.1}). If the minor version is omitted, it +is assumed to be @samp{0}. +The operator may be separated from the string @code{version} and +from the version number argument by whitespace. +The following example sets a variable if the Readline version being used +is 7.0 or newer: +@example +$if version >= 7.0 +set show-mode-in-prompt on +$endif +@end example + @item application The @var{application} construct is used to include application-specific settings. Each program using the Readline @@ -949,6 +974,23 @@ $if Bash "\C-xq": "\eb\"\ef\"" $endif @end example + +@item variable +The @var{variable} construct provides simple equality tests for Readline +variables and values. +The permitted comparison operators are @samp{=}, @samp{==}, and @samp{!=}. +The variable name must be separated from the comparison operator by +whitespace; the operator may be separated from the value on the right hand +side by whitespace. +Both string and boolean variables may be tested. Boolean variables must be +tested against the values @var{on} and @var{off}. +The following example is equivalent to the @code{mode=emacs} test described +above: +@example +$if editing-mode == emacs +set show-mode-in-prompt on +$endif +@end example @end table @item $endif @@ -1138,6 +1180,19 @@ Move back to the start of the current or previous word. Words are delimited by non-quoted shell metacharacters. @end ifset +@item previous-screen-line () +Attempt to move point to the same physical screen column on the previous +physical screen line. This will not have the desired effect if the current +Readline line does not take up more than one physical line or if point is not +greater than the length of the prompt plus the screen width. + +@item next-screen-line () +Attempt to move point to the same physical screen column on the next +physical screen line. This will not have the desired effect if the current +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-screen (C-l) Clear the screen and redraw the current line, leaving the current line at the top of the screen. @@ -1216,14 +1271,14 @@ The search string must match at the beginning of a history line. This is a non-incremental search. By default, this command is unbound. -@item history-substr-search-forward () +@item history-substring-search-forward () Search forward through the history for the string of characters between the start of the current line and the point. The search string may match anywhere in a history line. This is a non-incremental search. By default, this command is unbound. -@item history-substr-search-backward () +@item history-substring-search-backward () Search backward through the history for the string of characters between the start of the current line and the point. The search string may match anywhere in a history line. @@ -1590,9 +1645,10 @@ Abort the current editing command and ring the terminal's bell (subject to the setting of @code{bell-style}). -@item do-uppercase-version (M-a, M-b, M-@var{x}, @dots{}) -If the metafied character @var{x} is lowercase, run the command -that is bound to the corresponding uppercase character. +@item do-lowercase-version (M-A, M-B, M-@var{x}, @dots{}) +If the metafied character @var{x} is upper case, run the command +that is bound to the corresponding metafied lower case character. +The behavior is undefined if @var{x} is already lower case. @item prefix-meta (@key{ESC}) Metafy the next character typed. This is for keyboards @@ -1718,10 +1774,11 @@ 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. Any -argument is ignored. +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-xC-e) +@item edit-and-execute-command (C-x C-e) Invoke an editor on the current command line, and execute the result as shell commands. Bash attempts to invoke @@ -1816,7 +1873,9 @@ Next, the string specified as the argument to the @option{-W} option is considered. The string is first split using the characters in the @env{IFS} special variable as delimiters. -Shell quoting is honored. +Shell quoting is honored within the string, in order to provide a +mechanism for the words to contain shell metacharacters or characters +in the value of @env{IFS}. Each word is then expanded using brace expansion, tilde expansion, parameter and variable expansion, command substitution, and arithmetic expansion, @@ -2200,7 +2259,7 @@ a shell function and bind it to a particular command using @code{complete -F}. The following function provides completions for the @code{cd} builtin. It is a reasonably good example of what shell functions must do when -used for completion. This function uses the word passsed as @code{$2} +used for completion. This function uses the word passed as @code{$2} to determine the directory name to complete. You can also use the @code{COMP_WORDS} array variable; the current word is indexed by the @code{COMP_CWORD} variable. diff --git a/lib/readline/doc/version.texi b/lib/readline/doc/version.texi index 9dc2998a..9fefcfae 100644 --- a/lib/readline/doc/version.texi +++ b/lib/readline/doc/version.texi @@ -1,10 +1,10 @@ @ignore -Copyright (C) 1988-2016 Free Software Foundation, Inc. +Copyright (C) 1988-2017 Free Software Foundation, Inc. @end ignore @set EDITION 7.0 @set VERSION 7.0 -@set UPDATED 16 July 2016 -@set UPDATED-MONTH July 2016 +@set UPDATED 28 December 2017 +@set UPDATED-MONTH December 2017 -@set LASTCHANGE Sat Jul 16 13:43:15 EDT 2016 +@set LASTCHANGE Thu Dec 28 14:44:16 EST 2017 diff --git a/lib/readline/emacs_keymap.c b/lib/readline/emacs_keymap.c index cb6e140a..b5e53f49 100644 --- a/lib/readline/emacs_keymap.c +++ b/lib/readline/emacs_keymap.c @@ -1,6 +1,6 @@ /* emacs_keymap.c -- the keymap for emacs_mode in readline (). */ -/* Copyright (C) 1987-2009 Free Software Foundation, Inc. +/* Copyright (C) 1987-2017 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. diff --git a/lib/readline/examples/rlcat.c b/lib/readline/examples/rlcat.c index fa9e06ff..b4942413 100644 --- a/lib/readline/examples/rlcat.c +++ b/lib/readline/examples/rlcat.c @@ -137,7 +137,7 @@ fcopy(fp) if (vflag && isascii ((unsigned char)c) && isprint((unsigned char)c) == 0) { x = rl_untranslate_keyseq (c); - if (fputs (x, stdout) != 0) + if (fputs (x, stdout) == EOF) return 1; } else if (putchar (c) == EOF) diff --git a/lib/readline/funmap.c b/lib/readline/funmap.c index 34b1d6ba..aaf144de 100644 --- a/lib/readline/funmap.c +++ b/lib/readline/funmap.c @@ -1,6 +1,6 @@ /* funmap.c -- attach names to functions. */ -/* Copyright (C) 1987-2016 Free Software Foundation, Inc. +/* Copyright (C) 1987-2017 Free Software Foundation, Inc. This file is part of the GNU Readline Library (Readline), a library for reading lines of text with interactive input and history editing. @@ -110,6 +110,7 @@ static const FUNMAP default_funmap[] = { { "menu-complete", rl_menu_complete }, { "menu-complete-backward", rl_backward_menu_complete }, { "next-history", rl_get_next_history }, + { "next-screen-line", rl_next_screen_line }, { "non-incremental-forward-search-history", rl_noninc_forward_search }, { "non-incremental-reverse-search-history", rl_noninc_reverse_search }, { "non-incremental-forward-search-history-again", rl_noninc_forward_search_again }, @@ -121,6 +122,7 @@ static const FUNMAP default_funmap[] = { #endif { "possible-completions", rl_possible_completions }, { "previous-history", rl_get_previous_history }, + { "previous-screen-line", rl_previous_screen_line }, { "print-last-kbd-macro", rl_print_last_kbd_macro }, { "quoted-insert", rl_quoted_insert }, { "re-read-init-file", rl_re_read_init_file }, @@ -204,9 +206,7 @@ static const FUNMAP default_funmap[] = { }; int -rl_add_funmap_entry (name, function) - const char *name; - rl_command_func_t *function; +rl_add_funmap_entry (const char *name, rl_command_func_t *function) { if (funmap_entry + 2 >= funmap_size) { @@ -226,7 +226,7 @@ static int funmap_initialized; /* Make the funmap contain all of the default entries. */ void -rl_initialize_funmap () +rl_initialize_funmap (void) { register int i; @@ -244,7 +244,7 @@ rl_initialize_funmap () is sorted. The array itself is allocated, but not the strings inside. You should free () the array when you done, but not the pointers. */ const char ** -rl_funmap_names () +rl_funmap_names (void) { const char **result; int result_size, result_index; diff --git a/lib/readline/histexpand.c b/lib/readline/histexpand.c index b84a6b8a..e9c333d7 100644 --- a/lib/readline/histexpand.c +++ b/lib/readline/histexpand.c @@ -1,6 +1,6 @@ /* histexpand.c -- history expansion. */ -/* Copyright (C) 1989-2015 Free Software Foundation, Inc. +/* Copyright (C) 1989-2017 Free Software Foundation, Inc. This file contains the GNU History Library (History), a set of routines for managing the text of previously typed lines. @@ -132,10 +132,7 @@ static char *search_match; So you might call this function like: line = get_history_event ("!echo:p", &index, 0); */ char * -get_history_event (string, caller_index, delimiting_quote) - const char *string; - int *caller_index; - int delimiting_quote; +get_history_event (const char *string, int *caller_index, int delimiting_quote) { register int i; register char c; @@ -316,9 +313,7 @@ get_history_event (string, caller_index, delimiting_quote) to the closing single quote. FLAGS currently used to allow backslash to escape a single quote (e.g., for bash $'...'). */ static void -hist_string_extract_single_quoted (string, sindex, flags) - char *string; - int *sindex, flags; +hist_string_extract_single_quoted (char *string, int *sindex, int flags) { register int i; @@ -332,8 +327,7 @@ hist_string_extract_single_quoted (string, sindex, flags) } static char * -quote_breaks (s) - char *s; +quote_breaks (char *s) { register char *p, *r; char *ret; @@ -374,9 +368,7 @@ quote_breaks (s) } static char * -hist_error(s, start, current, errtype) - char *s; - int start, current, errtype; +hist_error(char *s, int start, int current, int errtype) { char *temp; const char *emsg; @@ -433,9 +425,7 @@ hist_error(s, start, current, errtype) subst_rhs is allowed to be set to the empty string. */ static char * -get_subst_pattern (str, iptr, delimiter, is_rhs, lenptr) - char *str; - int *iptr, delimiter, is_rhs, *lenptr; +get_subst_pattern (char *str, int *iptr, int delimiter, int is_rhs, int *lenptr) { register int si, i, j, k; char *s; @@ -490,7 +480,7 @@ get_subst_pattern (str, iptr, delimiter, is_rhs, lenptr) } static void -postproc_subst_rhs () +postproc_subst_rhs (void) { char *new; int i, j, new_size; @@ -526,12 +516,9 @@ postproc_subst_rhs () if the `p' modifier was supplied and the caller should just print the returned string. Returns the new index into string in *END_INDEX_PTR, and the expanded specifier in *RET_STRING. */ +/* need current line for !# */ static int -history_expand_internal (string, start, qc, end_index_ptr, ret_string, current_line) - char *string; - int start, qc, *end_index_ptr; - char **ret_string; - char *current_line; /* for !# */ +history_expand_internal (char *string, int start, int qc, int *end_index_ptr, char **ret_string, char *current_line) { int i, n, starting_index; int substitute_globally, subst_bywords, want_quotes, print_only; @@ -908,9 +895,7 @@ history_expand_internal (string, start, qc, end_index_ptr, ret_string, current_l while (0) int -history_expand (hstring, output) - char *hstring; - char **output; +history_expand (char *hstring, char **output) { register int j; int i, r, l, passc, cc, modified, eindex, only_printing, dquote, squote, flag; @@ -1249,9 +1234,7 @@ history_expand (hstring, output) CALLER_INDEX is the offset in SPEC to start looking; it is updated to point to just after the last character parsed. */ static char * -get_history_word_specifier (spec, from, caller_index) - char *spec, *from; - int *caller_index; +get_history_word_specifier (char *spec, char *from, int *caller_index) { register int i = *caller_index; int first, last; @@ -1357,9 +1340,7 @@ get_history_word_specifier (spec, from, caller_index) tokens, so that FIRST = -1 means the next to last token on the line). If LAST is `$' the last arg from STRING is used. */ char * -history_arg_extract (first, last, string) - int first, last; - const char *string; +history_arg_extract (int first, int last, const char *string) { register int i, len; char *result; @@ -1418,9 +1399,7 @@ history_arg_extract (first, last, string) } static int -history_tokenize_word (string, ind) - const char *string; - int ind; +history_tokenize_word (const char *string, int ind) { register int i, j; int delimiter, nestdelim, delimopen; @@ -1570,9 +1549,7 @@ get_word: } static char * -history_substring (string, start, end) - const char *string; - int start, end; +history_substring (const char *string, int start, int end) { register int len; register char *result; @@ -1589,9 +1566,7 @@ history_substring (string, start, end) WIND. The position in the returned array of strings is returned in *INDP. */ static char ** -history_tokenize_internal (string, wind, indp) - const char *string; - int wind, *indp; +history_tokenize_internal (const char *string, int wind, int *indp) { char **result; register int i, start, result_index, size; @@ -1644,17 +1619,14 @@ history_tokenize_internal (string, wind, indp) /* Return an array of tokens, much as the shell might. The tokens are parsed out of STRING. */ char ** -history_tokenize (string) - const char *string; +history_tokenize (const char *string) { return (history_tokenize_internal (string, -1, (int *)NULL)); } /* Free members of WORDS from START to an empty string */ static void -freewords (words, start) - char **words; - int start; +freewords (char **words, int start) { register int i; @@ -1666,9 +1638,7 @@ freewords (words, start) in the history line LINE. Used to save the word matched by the last history !?string? search. */ static char * -history_find_word (line, ind) - char *line; - int ind; +history_find_word (char *line, int ind) { char **words, *s; int i, wind; diff --git a/lib/readline/histfile.c b/lib/readline/histfile.c index 5b057cde..399bcc39 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-2016 Free Software Foundation, Inc. +/* Copyright (C) 1989-2017 Free Software Foundation, Inc. This file contains the GNU History Library (History), a set of routines for managing the text of previously typed lines. @@ -143,8 +143,7 @@ static int histfile_restore PARAMS((const char *, const char *)); filename. This only matters when you don't specify the filename to read_history (), or write_history (). */ static char * -history_filename (filename) - const char *filename; +history_filename (const char *filename) { char *return_val; const char *home; @@ -179,8 +178,7 @@ history_filename (filename) } static char * -history_backupfile (filename) - const char *filename; +history_backupfile (const char *filename) { const char *fn; char *ret, linkbuf[PATH_MAX+1]; @@ -208,8 +206,7 @@ history_backupfile (filename) } static char * -history_tempfile (filename) - const char *filename; +history_tempfile (const char *filename) { const char *fn; char *ret, linkbuf[PATH_MAX+1]; @@ -251,8 +248,7 @@ history_tempfile (filename) If FILENAME is NULL, then read from ~/.history. Returns 0 if successful, or errno if not. */ int -read_history (filename) - const char *filename; +read_history (const char *filename) { return (read_history_range (filename, 0, -1)); } @@ -263,9 +259,7 @@ read_history (filename) until the end of the file. If FILENAME is NULL, then read from ~/.history. Returns 0 if successful, or errno if not. */ int -read_history_range (filename, from, to) - const char *filename; - int from, to; +read_history_range (const char *filename, int from, int to) { register char *line_start, *line_end, *p; char *input, *buffer, *bufend, *last_ts; @@ -289,6 +283,16 @@ read_history_range (filename, from, to) if ((file < 0) || (fstat (file, &finfo) == -1)) goto error_and_exit; + if (S_ISREG (finfo.st_mode) == 0) + { +#ifdef EFTYPE + errno = EFTYPE; +#else + errno = EINVAL; +#endif + goto error_and_exit; + } + file_size = (size_t)finfo.st_size; /* check for overflow on very large files */ @@ -298,6 +302,12 @@ read_history_range (filename, from, to) goto error_and_exit; } + if (file_size == 0) + { + free (input); + return 0; /* don't waste time if we don't have to */ + } + #ifdef HISTORY_USE_MMAP /* We map read/write and private so we can change newlines to NULs without affecting the underlying object. */ @@ -344,6 +354,7 @@ read_history_range (filename, from, to) /* Start at beginning of file, work to end. */ bufend = buffer + chars_read; + *bufend = '\0'; /* null-terminate buffer for timestamp checks */ current_line = 0; /* Heuristic: the history comment character rarely changes, so assume we @@ -427,9 +438,7 @@ read_history_range (filename, from, to) /* Save FILENAME to BACK, handling case where FILENAME is a symlink (e.g., ~/.bash_history -> .histfiles/.bash_history.$HOSTNAME) */ static int -histfile_backup (filename, back) - const char *filename; - const char *back; +histfile_backup (const char *filename, const char *back) { #if defined (HAVE_READLINK) char linkbuf[PATH_MAX+1]; @@ -448,9 +457,7 @@ histfile_backup (filename, back) /* Restore ORIG from BACKUP handling case where ORIG is a symlink (e.g., ~/.bash_history -> .histfiles/.bash_history.$HOSTNAME) */ static int -histfile_restore (backup, orig) - const char *backup; - const char *orig; +histfile_restore (const char *backup, const char *orig) { #if defined (HAVE_READLINK) char linkbuf[PATH_MAX+1]; @@ -470,9 +477,7 @@ histfile_restore (backup, orig) 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. */ int -history_truncate_file (fname, lines) - const char *fname; - int lines; +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; @@ -606,12 +611,14 @@ history_truncate_file (fname, lines) history_lines_written_to_file = 0; } +#if defined (HAVE_CHOWN) /* Make sure the new filename is owned by the same user as the old. If one 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) r = chown (filename, finfo.st_uid, finfo.st_gid); +#endif xfree (filename); FREE (tempname); @@ -623,9 +630,7 @@ history_truncate_file (fname, lines) from the history list to FILENAME. OVERWRITE is non-zero if you wish to replace FILENAME with the entries. */ static int -history_do_write (filename, nelements, overwrite) - const char *filename; - int nelements, overwrite; +history_do_write (const char *filename, int nelements, int overwrite) { register int i; char *output, *tempname, *histname; @@ -753,12 +758,14 @@ mmap_error: history_lines_written_to_file = 0; } +#if defined (HAVE_CHOWN) /* Make sure the new filename is owned by the same user as the old. If one 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) mode = chown (histname, finfo.st_uid, finfo.st_gid); +#endif FREE (histname); FREE (tempname); @@ -769,9 +776,7 @@ mmap_error: /* Append NELEMENT entries to FILENAME. The entries appended are from the end of the list minus NELEMENTs up to the end of the list. */ int -append_history (nelements, filename) - int nelements; - const char *filename; +append_history (int nelements, const char *filename) { return (history_do_write (filename, nelements, HISTORY_APPEND)); } @@ -780,8 +785,7 @@ append_history (nelements, filename) then write the history list to ~/.history. Values returned are as in read_history ().*/ int -write_history (filename) - const char *filename; +write_history (const char *filename) { return (history_do_write (filename, history_length, HISTORY_OVERWRITE)); } diff --git a/lib/readline/histlib.h b/lib/readline/histlib.h index 28cad14a..9627b245 100644 --- a/lib/readline/histlib.h +++ b/lib/readline/histlib.h @@ -51,9 +51,9 @@ #endif #ifndef member -# ifndef strchr +# if !defined (strchr) && !defined (__STDC__) extern char *strchr (); -# endif +# endif /* !strchr && !__STDC__ */ #define member(c, s) ((c) ? ((char *)strchr ((s), (c)) != (char *)NULL) : 0) #endif @@ -69,11 +69,17 @@ extern char *strchr (); #define NO_PREV_SUBST 4 /* Possible definitions for history starting point specification. */ -#define ANCHORED_SEARCH 1 -#define NON_ANCHORED_SEARCH 0 +#define NON_ANCHORED_SEARCH 0 +#define ANCHORED_SEARCH 0x01 +#define PATTERN_SEARCH 0x02 /* Possible definitions for what style of writing the history file we want. */ #define HISTORY_APPEND 0 #define HISTORY_OVERWRITE 1 +/* internal extern function declarations used by other parts of the library */ + +/* histsearch.c */ +extern int _hs_history_patsearch PARAMS((const char *, int, int)); + #endif /* !_HISTLIB_H_ */ diff --git a/lib/readline/history.c b/lib/readline/history.c index 129c57a3..67158b14 100644 --- a/lib/readline/history.c +++ b/lib/readline/history.c @@ -1,6 +1,6 @@ /* history.c -- standalone history library */ -/* Copyright (C) 1989-2015 Free Software Foundation, Inc. +/* Copyright (C) 1989-2017 Free Software Foundation, Inc. This file contains the GNU History Library (History), a set of routines for managing the text of previously typed lines. @@ -97,7 +97,7 @@ int history_base = 1; /* Return the current HISTORY_STATE of the history. */ HISTORY_STATE * -history_get_history_state () +history_get_history_state (void) { HISTORY_STATE *state; @@ -115,8 +115,7 @@ history_get_history_state () /* Set the state of the current history array to STATE. */ void -history_set_history_state (state) - HISTORY_STATE *state; +history_set_history_state (HISTORY_STATE *state) { the_history = state->entries; history_offset = state->offset; @@ -129,7 +128,7 @@ history_set_history_state (state) /* Begin a session in which the history functions might be used. This initializes interactive variables. */ void -using_history () +using_history (void) { history_offset = history_length; } @@ -138,7 +137,7 @@ using_history () This just adds up the lengths of the_history->lines and the associated timestamps. */ int -history_total_bytes () +history_total_bytes (void) { register int i, result; @@ -151,7 +150,7 @@ history_total_bytes () /* Returns the magic number which says what history element we are looking at now. In this implementation, it returns history_offset. */ int -where_history () +where_history (void) { return (history_offset); } @@ -159,8 +158,7 @@ where_history () /* Make the current history item be the one at POS, an absolute index. Returns zero if POS is out of range, else non-zero. */ int -history_set_pos (pos) - int pos; +history_set_pos (int pos) { if (pos > history_length || pos < 0 || !the_history) return (0); @@ -172,7 +170,7 @@ history_set_pos (pos) is the actual array of data, and could be bashed or made corrupt easily. The array is terminated with a NULL pointer. */ HIST_ENTRY ** -history_list () +history_list (void) { return (the_history); } @@ -180,7 +178,7 @@ history_list () /* Return the history entry at the current position, as determined by history_offset. If there is no entry there, return a NULL pointer. */ HIST_ENTRY * -current_history () +current_history (void) { return ((history_offset == history_length) || the_history == 0) ? (HIST_ENTRY *)NULL @@ -191,7 +189,7 @@ current_history () a pointer to that entry. If there is no previous entry then return a NULL pointer. */ HIST_ENTRY * -previous_history () +previous_history (void) { return history_offset ? the_history[--history_offset] : (HIST_ENTRY *)NULL; } @@ -200,7 +198,7 @@ previous_history () a pointer to that entry. If there is no next entry then return a NULL pointer. */ HIST_ENTRY * -next_history () +next_history (void) { return (history_offset == history_length) ? (HIST_ENTRY *)NULL : the_history[++history_offset]; } @@ -208,8 +206,7 @@ next_history () /* Return the history entry which is logically at OFFSET in the history array. OFFSET is relative to history_base. */ HIST_ENTRY * -history_get (offset) - int offset; +history_get (int offset) { int local_index; @@ -220,9 +217,7 @@ history_get (offset) } HIST_ENTRY * -alloc_history_entry (string, ts) - char *string; - char *ts; +alloc_history_entry (char *string, char *ts) { HIST_ENTRY *temp; @@ -236,8 +231,7 @@ alloc_history_entry (string, ts) } time_t -history_get_time (hist) - HIST_ENTRY *hist; +history_get_time (HIST_ENTRY *hist) { char *ts; time_t t; @@ -255,7 +249,7 @@ history_get_time (hist) } static char * -hist_inittime () +hist_inittime (void) { time_t t; char ts[64], *ret; @@ -275,8 +269,7 @@ hist_inittime () /* Place STRING at the end of the history list. The data field is set to NULL. */ void -add_history (string) - const char *string; +add_history (const char *string) { HIST_ENTRY *temp; int new_length; @@ -335,8 +328,7 @@ add_history (string) /* Change the time stamp of the most recent history entry to STRING. */ void -add_history_time (string) - const char *string; +add_history_time (const char *string) { HIST_ENTRY *hs; @@ -350,8 +342,7 @@ add_history_time (string) /* Free HIST and return the data so the calling application can free it if necessary and desired. */ histdata_t -free_history_entry (hist) - HIST_ENTRY *hist; +free_history_entry (HIST_ENTRY *hist) { histdata_t x; @@ -365,8 +356,7 @@ free_history_entry (hist) } HIST_ENTRY * -copy_history_entry (hist) - HIST_ENTRY *hist; +copy_history_entry (HIST_ENTRY *hist) { HIST_ENTRY *ret; char *ts; @@ -388,10 +378,7 @@ copy_history_entry (hist) the old entry so you can dispose of the data. In the case of an invalid WHICH, a NULL pointer is returned. */ HIST_ENTRY * -replace_history_entry (which, line, data) - int which; - const char *line; - histdata_t data; +replace_history_entry (int which, const char *line, histdata_t data) { HIST_ENTRY *temp, *old_value; @@ -413,17 +400,26 @@ replace_history_entry (which, line, data) end of the current line first. This can be used to construct multi-line history entries while reading lines from the history file. */ void -_hs_append_history_line (which, line) - int which; - const char *line; +_hs_append_history_line (int which, const char *line) { HIST_ENTRY *hent; - size_t newlen, curlen; + size_t newlen, curlen, minlen; char *newline; hent = the_history[which]; curlen = strlen (hent->line); - newlen = curlen + strlen (line) + 2; + minlen = curlen + strlen (line) + 2; /* min space needed */ + if (curlen > 256) /* XXX - for now */ + { + newlen = 512; /* now realloc in powers of 2 */ + /* we recalcluate every time; the operations are cheap */ + while (newlen < minlen) + newlen <<= 1; + } + else + newlen = minlen; + /* Assume that realloc returns the same pointer and doesn't try a new + alloc/copy if the new size is the same as the one last passed. */ newline = realloc (hent->line, newlen); if (newline) { @@ -440,9 +436,7 @@ _hs_append_history_line (which, line) WHICH >= 0 means to replace that particular history entry's data, as long as it matches OLD. */ void -_hs_replace_history_data (which, old, new) - int which; - histdata_t *old, *new; +_hs_replace_history_data (int which, histdata_t *old, histdata_t *new) { HIST_ENTRY *entry; register int i, last; @@ -482,29 +476,76 @@ _hs_replace_history_data (which, old, new) element is returned to you so you can free the line, data, and containing structure. */ HIST_ENTRY * -remove_history (which) - int which; +remove_history (int which) { HIST_ENTRY *return_value; register int i; +#if 1 + int nentries; + HIST_ENTRY **start, **end; +#endif if (which < 0 || which >= history_length || history_length == 0 || the_history == 0) return ((HIST_ENTRY *)NULL); return_value = the_history[which]; +#if 1 + /* Copy the rest of the entries, moving down one slot. Copy includes + trailing NULL. */ + nentries = history_length - which; + start = the_history + which; + end = start + 1; + memmove (start, end, nentries * sizeof (HIST_ENTRY *)); +#else for (i = which; i < history_length; i++) the_history[i] = the_history[i + 1]; +#endif history_length--; return (return_value); } +HIST_ENTRY ** +remove_history_range (int first, int last) +{ + HIST_ENTRY **return_value; + register int i; + int nentries; + HIST_ENTRY **start, **end; + + if (the_history == 0 || history_length == 0) + return ((HIST_ENTRY **)NULL); + if (first < 0 || first >= history_length || last < 0 || last >= history_length) + return ((HIST_ENTRY **)NULL); + if (first > last) + return (HIST_ENTRY **)NULL; + + nentries = last - first + 1; + return_value = (HIST_ENTRY **)malloc ((nentries + 1) * sizeof (HIST_ENTRY *)); + if (return_value == 0) + return return_value; + + /* Return all the deleted entries in a list */ + for (i = first ; i <= last; i++) + return_value[i - first] = the_history[i]; + return_value[i - first] = (HIST_ENTRY *)NULL; + + /* Copy the rest of the entries, moving down NENTRIES slots. Copy includes + trailing NULL. */ + start = the_history + first; + end = the_history + last + 1; + memmove (start, end, (history_length - last) * sizeof (HIST_ENTRY *)); + + history_length -= nentries; + + return (return_value); +} + /* Stifle the history list, remembering only MAX number of lines. */ void -stifle_history (max) - int max; +stifle_history (int max) { register int i, j; @@ -532,7 +573,7 @@ stifle_history (max) number of history entries. The value is positive if the history was stifled, negative if it wasn't. */ int -unstifle_history () +unstifle_history (void) { if (history_stifled) { @@ -544,13 +585,13 @@ unstifle_history () } int -history_is_stifled () +history_is_stifled (void) { return (history_stifled); } void -clear_history () +clear_history (void) { register int i; @@ -562,4 +603,5 @@ clear_history () } history_offset = history_length = 0; + history_base = 1; /* reset history base to default */ } diff --git a/lib/readline/history.h b/lib/readline/history.h index 8ce7c805..fceb99ca 100644 --- a/lib/readline/history.h +++ b/lib/readline/history.h @@ -86,11 +86,13 @@ extern void add_history PARAMS((const char *)); STRING. */ extern void add_history_time PARAMS((const char *)); -/* A reasonably useless function, only here for completeness. WHICH - is the magic number that tells us which element to delete. The - elements are numbered from 0. */ +/* Remove an entry from the history list. WHICH is the magic number that + tells us which element to delete. The elements are numbered from 0. */ extern HIST_ENTRY *remove_history PARAMS((int)); +/* Remove a set of entries from the history list: FIRST to LAST, inclusive */ +extern HIST_ENTRY **remove_history_range PARAMS((int, int)); + /* Allocate a history entry consisting of STRING and TIMESTAMP and return a pointer to it. */ extern HIST_ENTRY *alloc_history_entry PARAMS((char *, char *)); diff --git a/lib/readline/histsearch.c b/lib/readline/histsearch.c index 1ad55d22..b6771fda 100644 --- a/lib/readline/histsearch.c +++ b/lib/readline/histsearch.c @@ -1,6 +1,6 @@ /* histsearch.c -- searching the history list. */ -/* Copyright (C) 1989, 1992-2009 Free Software Foundation, Inc. +/* Copyright (C) 1989, 1992-2009,2017 Free Software Foundation, Inc. This file contains the GNU History Library (History), a set of routines for managing the text of previously typed lines. @@ -39,8 +39,13 @@ # include <unistd.h> #endif +#if defined (HAVE_FNMATCH) +# include <fnmatch.h> +#endif + #include "history.h" #include "histlib.h" +#include "xmalloc.h" /* The list of alternate characters that can delimit a history search string. */ @@ -59,18 +64,22 @@ static int history_search_internal PARAMS((const char *, int, int)); returned. */ static int -history_search_internal (string, direction, anchored) - const char *string; - int direction, anchored; +history_search_internal (const char *string, int direction, int flags) { register int i, reverse; register char *line; register int line_index; - int string_len; + int string_len, anchored, patsearch; HIST_ENTRY **the_history; /* local */ i = history_offset; reverse = (direction < 0); + anchored = (flags & ANCHORED_SEARCH); +#if defined (HAVE_FNMATCH) + patsearch = (flags & PATTERN_SEARCH); +#else + patsearch = 0; +#endif /* Take care of trivial cases first. */ if (string == 0 || *string == '\0') @@ -98,7 +107,7 @@ history_search_internal (string, direction, anchored) line_index = strlen (line); /* If STRING is longer than line, no match. */ - if (string_len > line_index) + if (patsearch == 0 && (string_len > line_index)) { NEXT_LINE (); continue; @@ -107,6 +116,17 @@ history_search_internal (string, direction, anchored) /* Handle anchored searches first. */ if (anchored == ANCHORED_SEARCH) { +#if defined (HAVE_FNMATCH) + if (patsearch) + { + if (fnmatch (string, line, 0) == 0) + { + history_offset = i; + return (0); + } + } + else +#endif if (STREQN (string, line, string_len)) { history_offset = i; @@ -120,10 +140,21 @@ history_search_internal (string, direction, anchored) /* Do substring search. */ if (reverse) { - line_index -= string_len; + line_index -= (patsearch == 0) ? string_len : 1; while (line_index >= 0) { +#if defined (HAVE_FNMATCH) + if (patsearch) + { + if (fnmatch (string, line + line_index, 0) == 0) + { + history_offset = i; + return (line_index); + } + } + else +#endif if (STREQN (string, line + line_index, string_len)) { history_offset = i; @@ -141,6 +172,17 @@ history_search_internal (string, direction, anchored) while (line_index < limit) { +#if defined (HAVE_FNMATCH) + if (patsearch) + { + if (fnmatch (string, line + line_index, 0) == 0) + { + history_offset = i; + return (line_index); + } + } + else +#endif if (STREQN (string, line + line_index, string_len)) { history_offset = i; @@ -153,20 +195,59 @@ history_search_internal (string, direction, anchored) } } +int +_hs_history_patsearch (const char *string, int direction, int flags) +{ + char *pat; + size_t len; + int ret, unescaped_backslash; + +#if defined (HAVE_FNMATCH) + /* Assume that the string passed does not have a leading `^' and any + anchored search request is captured in FLAGS */ + len = strlen (string); + ret = len - 1; + /* fnmatch is required to reject a pattern that ends with an unescaped + backslash */ + if (unescaped_backslash = (string[ret] == '\\')) + { + while (ret > 0 && string[--ret] == '\\') + unescaped_backslash = 1 - unescaped_backslash; + } + if (unescaped_backslash) + return -1; + pat = (char *)xmalloc (len + 2); + /* Attempt to reduce the number of searches by tacking a `*' onto the end + of a pattern that doesn't have one. Assume a pattern that ends in a + backslash contains an even number of trailing backslashes; we check + above */ + strcpy (pat, string); + if (pat[len - 1] != '*') + { + pat[len] = '*'; /* XXX */ + pat[len+1] = '\0'; + } +#else + pat = string; +#endif + + ret = history_search_internal (pat, direction, flags|PATTERN_SEARCH); + + if (pat != string) + free (pat); + return ret; +} + /* Do a non-anchored search for STRING through the history in DIRECTION. */ int -history_search (string, direction) - const char *string; - int direction; +history_search (const char *string, int direction) { return (history_search_internal (string, direction, NON_ANCHORED_SEARCH)); } /* Do an anchored search for string through the history in DIRECTION. */ int -history_search_prefix (string, direction) - const char *string; - int direction; +history_search_prefix (const char *string, int direction) { return (history_search_internal (string, direction, ANCHORED_SEARCH)); } @@ -175,9 +256,7 @@ history_search_prefix (string, direction) backwards. POS is an absolute index into the history list at which point to begin searching. */ int -history_search_pos (string, dir, pos) - const char *string; - int dir, pos; +history_search_pos (const char *string, int dir, int pos) { int ret, old; diff --git a/lib/readline/input.c b/lib/readline/input.c index 286897d7..00916456 100644 --- a/lib/readline/input.c +++ b/lib/readline/input.c @@ -1,6 +1,6 @@ /* input.c -- character input functions for readline. */ -/* Copyright (C) 1994-2015 Free Software Foundation, Inc. +/* Copyright (C) 1994-2017 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. @@ -76,6 +76,10 @@ extern int errno; # define O_NDELAY O_NONBLOCK /* Posix style */ #endif +#if defined (HAVE_PSELECT) +extern sigset_t _rl_orig_sigset; +#endif + /* Non-null means it is a pointer to a function to run while waiting for character input. */ rl_hook_func_t *rl_event_hook = (rl_hook_func_t *)NULL; @@ -98,6 +102,7 @@ static int rl_gather_tyi PARAMS((void)); /* Windows isatty returns true for every character device, including the null device, so we need to perform additional checks. */ #if defined (_WIN32) && !defined (__CYGWIN__) +#include <conio.h> #include <io.h> #define WIN32_LEAN_AND_MEAN 1 #include <windows.h> @@ -124,13 +129,13 @@ static int ibuffer_len = sizeof (ibuffer) - 1; #define any_typein (push_index != pop_index) int -_rl_any_typein () +_rl_any_typein (void) { return any_typein; } int -_rl_pushed_input_available () +_rl_pushed_input_available (void) { return (push_index != pop_index); } @@ -138,7 +143,7 @@ _rl_pushed_input_available () /* Return the amount of space available in the buffer for stuffing characters. */ static int -ibuffer_space () +ibuffer_space (void) { if (pop_index > push_index) return (pop_index - push_index - 1); @@ -150,8 +155,7 @@ ibuffer_space () Return the key in KEY. Result is non-zero if there was a key, or 0 if there wasn't. */ static int -rl_get_char (key) - int *key; +rl_get_char (int *key) { if (push_index == pop_index) return (0); @@ -171,8 +175,7 @@ rl_get_char (key) Returns non-zero if successful, zero if there is no space left in the buffer. */ int -_rl_unget_char (key) - int key; +_rl_unget_char (int key) { if (ibuffer_space ()) { @@ -189,7 +192,7 @@ _rl_unget_char (key) IBUFFER. Otherwise, just return. Returns number of characters read (0 if none available) and -1 on error (EIO). */ static int -rl_gather_tyi () +rl_gather_tyi (void) { int tty; register int tem, result; @@ -292,8 +295,7 @@ rl_gather_tyi () } int -rl_set_keyboard_input_timeout (u) - int u; +rl_set_keyboard_input_timeout (int u) { int o; @@ -310,7 +312,7 @@ rl_set_keyboard_input_timeout (u) the user, it should use _rl_input_queued(timeout_value_in_microseconds) instead. */ int -_rl_input_available () +_rl_input_available (void) { #if defined(HAVE_SELECT) fd_set readfds, exceptfds; @@ -352,8 +354,7 @@ _rl_input_available () } int -_rl_input_queued (t) - int t; +_rl_input_queued (int t) { int old_timeout, r; @@ -364,8 +365,7 @@ _rl_input_queued (t) } void -_rl_insert_typein (c) - int c; +_rl_insert_typein (int c) { int key, t, i; char *string; @@ -390,8 +390,7 @@ _rl_insert_typein (c) /* Add KEY to the buffer of characters to be read. Returns 1 if the character was stuffed correctly; 0 otherwise. */ int -rl_stuff_char (key) - int key; +rl_stuff_char (int key) { if (ibuffer_space () == 0) return 0; @@ -415,8 +414,7 @@ rl_stuff_char (key) /* Make C be the next command to be executed. */ int -rl_execute_next (c) - int c; +rl_execute_next (int c) { rl_pending_input = c; RL_SETSTATE (RL_STATE_INPUTPENDING); @@ -425,7 +423,7 @@ rl_execute_next (c) /* Clear any pending input pushed with rl_execute_next() */ int -rl_clear_pending_input () +rl_clear_pending_input (void) { rl_pending_input = 0; RL_UNSETSTATE (RL_STATE_INPUTPENDING); @@ -440,20 +438,20 @@ rl_clear_pending_input () /* Read a key, including pending input. */ int -rl_read_key () +rl_read_key (void) { int c, r; if (rl_pending_input) { - c = rl_pending_input; + c = rl_pending_input; /* XXX - cast to unsigned char if > 0? */ rl_clear_pending_input (); } else { /* If input is coming from a macro, then use that. */ if (c = _rl_next_macro_key ()) - return (c); + return ((unsigned char)c); /* If the user has an event function, then call it periodically. */ if (rl_event_hook) @@ -490,8 +488,7 @@ rl_read_key () } int -rl_getc (stream) - FILE *stream; +rl_getc (FILE *stream) { int result; unsigned char c; @@ -512,10 +509,15 @@ rl_getc (stream) #endif result = 0; #if defined (HAVE_PSELECT) - sigemptyset (&empty_set); FD_ZERO (&readfds); FD_SET (fileno (stream), &readfds); +# if defined (HANDLE_SIGNALS) + result = pselect (fileno (stream) + 1, &readfds, NULL, NULL, NULL, &_rl_orig_sigset); +# else + sigemptyset (&empty_set); + sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &empty_set); result = pselect (fileno (stream) + 1, &readfds, NULL, NULL, NULL, &empty_set); +# endif /* HANDLE_SIGNALS */ #endif if (result >= 0) result = read (fileno (stream), &c, sizeof (unsigned char)); @@ -602,9 +604,7 @@ handle_error: #if defined (HANDLE_MULTIBYTE) /* read multibyte char */ int -_rl_read_mbchar (mbchar, size) - char *mbchar; - int size; +_rl_read_mbchar (char *mbchar, int size) { int mb_len, c; size_t mbchar_bytes_length; @@ -653,12 +653,9 @@ _rl_read_mbchar (mbchar, size) may be FIRST. Used by the search functions, among others. Very similar to _rl_read_mbchar. */ int -_rl_read_mbstring (first, mb, mlen) - int first; - char *mb; - int mlen; +_rl_read_mbstring (int first, char *mb, int mlen) { - int i, c; + int i, c, n; mbstate_t ps; c = first; @@ -667,7 +664,8 @@ _rl_read_mbstring (first, mb, mlen) { mb[i] = (char)c; memset (&ps, 0, sizeof (mbstate_t)); - if (_rl_get_char_len (mb, &ps) == -2) + n = _rl_get_char_len (mb, &ps); + if (n == -2) { /* Read more for multibyte character */ RL_SETSTATE (RL_STATE_MOREINPUT); diff --git a/lib/readline/isearch.c b/lib/readline/isearch.c index 819fcbce..fa58e848 100644 --- a/lib/readline/isearch.c +++ b/lib/readline/isearch.c @@ -6,7 +6,7 @@ /* */ /* **************************************************************** */ -/* Copyright (C) 1987-2015 Free Software Foundation, Inc. +/* Copyright (C) 1987-2017 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. @@ -78,8 +78,7 @@ static int last_isearch_string_len; static char * const default_isearch_terminators = "\033\012"; _rl_search_cxt * -_rl_scxt_alloc (type, flags) - int type, flags; +_rl_scxt_alloc (int type, int flags) { _rl_search_cxt *cxt; @@ -120,9 +119,7 @@ _rl_scxt_alloc (type, flags) } void -_rl_scxt_dispose (cxt, flags) - _rl_search_cxt *cxt; - int flags; +_rl_scxt_dispose (_rl_search_cxt *cxt, int flags) { FREE (cxt->search_string); FREE (cxt->allocated_line); @@ -134,8 +131,7 @@ _rl_scxt_dispose (cxt, flags) /* Search backwards through the history looking for a string which is typed interactively. Start with the current line. */ int -rl_reverse_search_history (sign, key) - int sign, key; +rl_reverse_search_history (int sign, int key) { return (rl_search_history (-sign, key)); } @@ -143,8 +139,7 @@ rl_reverse_search_history (sign, key) /* Search forwards through the history looking for a string which is typed interactively. Start with the current line. */ int -rl_forward_search_history (sign, key) - int sign, key; +rl_forward_search_history (int sign, int key) { return (rl_search_history (sign, key)); } @@ -155,9 +150,7 @@ rl_forward_search_history (sign, key) WHERE is the history list number of the current line. If it is -1, then this line is the starting one. */ static void -rl_display_search (search_string, flags, where) - char *search_string; - int flags, where; +rl_display_search (char *search_string, int flags, int where) { char *message; int msglen, searchlen; @@ -206,8 +199,7 @@ rl_display_search (search_string, flags, where) } static _rl_search_cxt * -_rl_isearch_init (direction) - int direction; +_rl_isearch_init (int direction) { _rl_search_cxt *cxt; register int i; @@ -267,11 +259,10 @@ _rl_isearch_init (direction) } static void -_rl_isearch_fini (cxt) - _rl_search_cxt *cxt; +_rl_isearch_fini (_rl_search_cxt *cxt) { /* First put back the original state. */ - strcpy (rl_line_buffer, cxt->lines[cxt->save_line]); + rl_replace_line (cxt->lines[cxt->save_line], 0); rl_restore_prompt (); @@ -301,13 +292,13 @@ _rl_isearch_fini (cxt) rl_point = cxt->sline_index; /* Don't worry about where to put the mark here; rl_get_previous_history and rl_get_next_history take care of it. */ + _rl_fix_point (0); rl_clear_message (); } int -_rl_search_getchar (cxt) - _rl_search_cxt *cxt; +_rl_search_getchar (_rl_search_cxt *cxt) { int c; @@ -334,9 +325,7 @@ _rl_search_getchar (cxt) -1 if the caller should just free the context and return, 0 if we should break out of the loop, and 1 if we should continue to read characters. */ int -_rl_isearch_dispatch (cxt, c) - _rl_search_cxt *cxt; - int c; +_rl_isearch_dispatch (_rl_search_cxt *cxt, int c) { int n, wstart, wlen, limit, cval; rl_command_func_t *f; @@ -527,7 +516,7 @@ add_character: } return (1); } - else if (cxt->sflags & SF_REVERSE) + else if ((cxt->sflags & SF_REVERSE) && cxt->sline_index >= 0) cxt->sline_index--; else if (cxt->sline_index != cxt->sline_len) cxt->sline_index++; @@ -676,6 +665,12 @@ add_character: } else cxt->sline_index += cxt->direction; + + if (cxt->sline_index < 0) + { + cxt->sline_index = 0; + break; + } } if (cxt->sflags & SF_FOUND) break; @@ -703,7 +698,12 @@ add_character: (cxt->search_string_index > cxt->sline_len)); if (cxt->sflags & SF_FAILED) - break; + { + /* XXX - reset sline_index if < 0 */ + if (cxt->sline_index < 0) + cxt->sline_index = 0; + break; + } /* Now set up the line for searching... */ cxt->sline_index = (cxt->sflags & SF_REVERSE) ? cxt->sline_len - cxt->search_string_index : 0; @@ -734,9 +734,7 @@ add_character: } int -_rl_isearch_cleanup (cxt, r) - _rl_search_cxt *cxt; - int r; +_rl_isearch_cleanup (_rl_search_cxt *cxt, int r) { if (r >= 0) _rl_isearch_fini (cxt); @@ -753,8 +751,7 @@ _rl_isearch_cleanup (cxt, r) DIRECTION is which direction to search; >= 0 means forward, < 0 means backwards. */ static int -rl_search_history (direction, invoking_key) - int direction, invoking_key; +rl_search_history (int direction, int invoking_key) { _rl_search_cxt *cxt; /* local for now, but saved globally */ int c, r; @@ -792,8 +789,7 @@ rl_search_history (direction, invoking_key) If _rl_isearch_dispatch finishes searching, this function is responsible for turning off RL_STATE_ISEARCH, which it does using _rl_isearch_cleanup. */ int -_rl_isearch_callback (cxt) - _rl_search_cxt *cxt; +_rl_isearch_callback (_rl_search_cxt *cxt) { int c, r; diff --git a/lib/readline/keymaps.c b/lib/readline/keymaps.c index 58661e29..4ade30bc 100644 --- a/lib/readline/keymaps.c +++ b/lib/readline/keymaps.c @@ -1,6 +1,6 @@ /* keymaps.c -- Functions and keymaps for the GNU Readline library. */ -/* Copyright (C) 1988,1989-2009 Free Software Foundation, Inc. +/* Copyright (C) 1988,1989-2009,2017 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. @@ -54,7 +54,7 @@ /* Return a new, empty keymap. Free it with free() when you are done. */ Keymap -rl_make_bare_keymap () +rl_make_bare_keymap (void) { register int i; Keymap keymap; @@ -77,11 +77,25 @@ rl_make_bare_keymap () return (keymap); } +/* A convenience function that returns 1 if there are no keys bound to + functions in KEYMAP */ +int +rl_empty_keymap (Keymap keymap) +{ + int i; + + for (i = 0; i < ANYOTHERKEY; i++) + { + if (keymap[i].type != ISFUNC || keymap[i].function) + return 0; + } + return 1; +} + /* Return a new keymap which is a copy of MAP. Just copies pointers, does not copy text of macros or descend into child keymaps. */ Keymap -rl_copy_keymap (map) - Keymap map; +rl_copy_keymap (Keymap map) { register int i; Keymap temp; @@ -99,7 +113,7 @@ rl_copy_keymap (map) the uppercase Meta characters bound to run their lowercase equivalents, and the Meta digits bound to produce numeric arguments. */ Keymap -rl_make_keymap () +rl_make_keymap (void) { register int i; Keymap newmap; @@ -125,8 +139,7 @@ rl_make_keymap () /* Free the storage associated with MAP. */ void -rl_discard_keymap (map) - Keymap map; +rl_discard_keymap (Keymap map) { int i; @@ -154,8 +167,7 @@ rl_discard_keymap (map) /* Convenience function that discards, then frees, MAP. */ void -rl_free_keymap (map) - Keymap map; +rl_free_keymap (Keymap map) { rl_discard_keymap (map); xfree ((char *)map); diff --git a/lib/readline/kill.c b/lib/readline/kill.c index 696f1938..983a9848 100644 --- a/lib/readline/kill.c +++ b/lib/readline/kill.c @@ -1,6 +1,6 @@ /* kill.c -- kill ring management. */ -/* Copyright (C) 1994-2015 Free Software Foundation, Inc. +/* Copyright (C) 1994-2017 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. @@ -78,8 +78,7 @@ static int rl_yank_nth_arg_internal PARAMS((int, int, int)); /* How to say that you only want to save a certain amount of kill material. */ int -rl_set_retained_kills (num) - int num; +rl_set_retained_kills (int num) { return 0; } @@ -89,9 +88,7 @@ rl_set_retained_kills (num) non-zero, and the last command was a kill, the text is appended to the current kill ring slot, otherwise prepended. */ static int -_rl_copy_to_kill_ring (text, append) - char *text; - int append; +_rl_copy_to_kill_ring (char *text, int append) { char *old, *new; int slot; @@ -122,7 +119,7 @@ _rl_copy_to_kill_ring (text, append) else { slot = rl_kill_ring_length += 1; - rl_kill_ring = (char **)xrealloc (rl_kill_ring, slot * sizeof (char *)); + rl_kill_ring = (char **)xrealloc (rl_kill_ring, (slot + 1) * sizeof (char *)); } rl_kill_ring[--slot] = (char *)NULL; } @@ -131,7 +128,7 @@ _rl_copy_to_kill_ring (text, append) slot = rl_kill_ring_length - 1; /* If the last command was a kill, prepend or append. */ - if (_rl_last_command_was_kill && rl_editing_mode != vi_mode) + if (_rl_last_command_was_kill && rl_kill_ring[slot] && rl_editing_mode != vi_mode) { old = rl_kill_ring[slot]; new = (char *)xmalloc (1 + strlen (old) + strlen (text)); @@ -163,8 +160,7 @@ _rl_copy_to_kill_ring (text, append) last command was not a kill command, then a new slot is made for this kill. */ int -rl_kill_text (from, to) - int from, to; +rl_kill_text (int from, int to) { char *text; @@ -198,8 +194,7 @@ rl_kill_text (from, to) /* Delete the word at point, saving the text in the kill ring. */ int -rl_kill_word (count, key) - int count, key; +rl_kill_word (int count, int key) { int orig_point; @@ -222,17 +217,16 @@ rl_kill_word (count, key) /* Rubout the word before point, placing it on the kill ring. */ int -rl_backward_kill_word (count, ignore) - int count, ignore; +rl_backward_kill_word (int count, int key) { int orig_point; if (count < 0) - return (rl_kill_word (-count, ignore)); + return (rl_kill_word (-count, key)); else { orig_point = rl_point; - rl_backward_word (count, ignore); + rl_backward_word (count, key); if (rl_point != orig_point) rl_kill_text (orig_point, rl_point); @@ -246,17 +240,16 @@ rl_backward_kill_word (count, ignore) /* Kill from here to the end of the line. If DIRECTION is negative, kill back to the line start instead. */ int -rl_kill_line (direction, ignore) - int direction, ignore; +rl_kill_line (int direction, int key) { int orig_point; if (direction < 0) - return (rl_backward_kill_line (1, ignore)); + return (rl_backward_kill_line (1, key)); else { orig_point = rl_point; - rl_end_of_line (1, ignore); + rl_end_of_line (1, key); if (orig_point != rl_point) rl_kill_text (orig_point, rl_point); rl_point = orig_point; @@ -269,13 +262,12 @@ rl_kill_line (direction, ignore) /* Kill backwards to the start of the line. If DIRECTION is negative, kill forwards to the line end instead. */ int -rl_backward_kill_line (direction, ignore) - int direction, ignore; +rl_backward_kill_line (int direction, int key) { int orig_point; if (direction < 0) - return (rl_kill_line (1, ignore)); + return (rl_kill_line (1, key)); else { if (rl_point == 0) @@ -283,7 +275,7 @@ rl_backward_kill_line (direction, ignore) else { orig_point = rl_point; - rl_beg_of_line (1, ignore); + rl_beg_of_line (1, key); if (rl_point != orig_point) rl_kill_text (orig_point, rl_point); if (rl_editing_mode == emacs_mode) @@ -295,8 +287,7 @@ rl_backward_kill_line (direction, ignore) /* Kill the whole line, no matter where point is. */ int -rl_kill_full_line (count, ignore) - int count, ignore; +rl_kill_full_line (int count, int key) { rl_begin_undo_group (); rl_point = 0; @@ -313,8 +304,7 @@ rl_kill_full_line (count, ignore) /* This does what C-w does in Unix. We can't prevent people from using behaviour that they expect. */ int -rl_unix_word_rubout (count, key) - int count, key; +rl_unix_word_rubout (int count, int key) { int orig_point; @@ -346,8 +336,7 @@ rl_unix_word_rubout (count, key) /* This deletes one filename component in a Unix pathname. That is, it deletes backward to directory separator (`/') or whitespace. */ int -rl_unix_filename_rubout (count, key) - int count, key; +rl_unix_filename_rubout (int count, int key) { int orig_point, c; @@ -390,8 +379,7 @@ rl_unix_filename_rubout (count, key) into the line at all, and if you aren't, then you know what you are doing. */ int -rl_unix_line_discard (count, key) - int count, key; +rl_unix_line_discard (int count, int key) { if (rl_point == 0) rl_ding (); @@ -408,8 +396,7 @@ rl_unix_line_discard (count, key) /* Copy the text in the `region' to the kill ring. If DELETE is non-zero, delete the text from the line as well. */ static int -region_kill_internal (delete) - int delete; +region_kill_internal (int delete) { char *text; @@ -427,16 +414,14 @@ region_kill_internal (delete) /* Copy the text in the region to the kill ring. */ int -rl_copy_region_to_kill (count, ignore) - int count, ignore; +rl_copy_region_to_kill (int count, int key) { return (region_kill_internal (0)); } /* Kill the text between the point and mark. */ int -rl_kill_region (count, ignore) - int count, ignore; +rl_kill_region (int count, int key) { int r, npoint; @@ -450,8 +435,7 @@ rl_kill_region (count, ignore) /* Copy COUNT words to the kill ring. DIR says which direction we look to find the words. */ static int -_rl_copy_word_as_kill (count, dir) - int count, dir; +_rl_copy_word_as_kill (int count, int dir) { int om, op, r; @@ -479,8 +463,7 @@ _rl_copy_word_as_kill (count, dir) } int -rl_copy_forward_word (count, key) - int count, key; +rl_copy_forward_word (int count, int key) { if (count < 0) return (rl_copy_backward_word (-count, key)); @@ -489,8 +472,7 @@ rl_copy_forward_word (count, key) } int -rl_copy_backward_word (count, key) - int count, key; +rl_copy_backward_word (int count, int key) { if (count < 0) return (rl_copy_forward_word (-count, key)); @@ -500,8 +482,7 @@ rl_copy_backward_word (count, key) /* Yank back the last killed text. This ignores arguments. */ int -rl_yank (count, ignore) - int count, ignore; +rl_yank (int count, int key) { if (rl_kill_ring == 0) { @@ -519,8 +500,7 @@ rl_yank (count, ignore) delete that text from the line, rotate the index down, and yank back some other text. */ int -rl_yank_pop (count, key) - int count, key; +rl_yank_pop (int count, int key) { int l, n; @@ -552,8 +532,7 @@ rl_yank_pop (count, key) #if defined (VI_MODE) int -rl_vi_yank_pop (count, key) - int count, key; +rl_vi_yank_pop (int count, int key) { int l, n; @@ -587,8 +566,7 @@ rl_vi_yank_pop (count, key) /* Yank the COUNTh argument from the previous history line, skipping HISTORY_SKIP lines before looking for the `previous line'. */ static int -rl_yank_nth_arg_internal (count, ignore, history_skip) - int count, ignore, history_skip; +rl_yank_nth_arg_internal (int count, int key, int history_skip) { register HIST_ENTRY *entry; char *arg; @@ -629,7 +607,7 @@ rl_yank_nth_arg_internal (count, ignore, history_skip) inserts it right *after* rl_point. */ if (rl_editing_mode == vi_mode) { - rl_vi_append_mode (1, ignore); + rl_vi_append_mode (1, key); rl_insert_text (" "); } #endif /* VI_MODE */ @@ -643,18 +621,16 @@ rl_yank_nth_arg_internal (count, ignore, history_skip) /* Yank the COUNTth argument from the previous history line. */ int -rl_yank_nth_arg (count, ignore) - int count, ignore; +rl_yank_nth_arg (int count, int key) { - return (rl_yank_nth_arg_internal (count, ignore, 0)); + return (rl_yank_nth_arg_internal (count, key, 0)); } /* Yank the last argument from the previous history line. This `knows' how rl_yank_nth_arg treats a count of `$'. With an argument, this behaves the same as rl_yank_nth_arg. */ int -rl_yank_last_arg (count, key) - int count, key; +rl_yank_last_arg (int count, int key) { static int history_skip = 0; static int explicit_arg_p = 0; @@ -695,8 +671,7 @@ rl_yank_last_arg (count, key) closing sequence and insert the pasted text as a single unit without interpretation. */ int -rl_bracketed_paste_begin (count, key) - int count, key; +rl_bracketed_paste_begin (int count, int key) { int retval, c; size_t len, cap; @@ -740,13 +715,12 @@ rl_bracketed_paste_begin (count, key) return (retval); } -/* A special paste command for Windows users.. */ +/* A special paste command for Windows users. */ #if defined (_WIN32) #include <windows.h> int -rl_paste_from_clipboard (count, key) - int count, key; +rl_paste_from_clipboard (int count, int key) { char *data, *ptr; int len; diff --git a/lib/readline/macro.c b/lib/readline/macro.c index c7017cc6..92cc55c3 100644 --- a/lib/readline/macro.c +++ b/lib/readline/macro.c @@ -1,6 +1,6 @@ /* macro.c -- keyboard macros for readline. */ -/* Copyright (C) 1994-2009 Free Software Foundation, Inc. +/* Copyright (C) 1994-2009,2017 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. @@ -49,6 +49,8 @@ #include "rlprivate.h" #include "xmalloc.h" +#define MAX_MACRO_LEVEL 16 + /* **************************************************************** */ /* */ /* Hacking Keyboard Macros */ @@ -83,13 +85,24 @@ struct saved_macro { /* The list of saved macros. */ static struct saved_macro *macro_list = (struct saved_macro *)NULL; +static int macro_level = 0; + /* Set up to read subsequent input from STRING. STRING is free ()'ed when we are done with it. */ void -_rl_with_macro_input (string) - char *string; +_rl_with_macro_input (char *string) { - _rl_push_executing_macro (); + if (macro_level > MAX_MACRO_LEVEL) + { + _rl_errmsg ("maximum macro execution nesting level exceeded"); + _rl_abort_internal (); + return; + } + +#if 0 + if (rl_executing_macro) /* XXX - later */ +#endif + _rl_push_executing_macro (); rl_executing_macro = string; executing_macro_index = 0; RL_SETSTATE(RL_STATE_MACROINPUT); @@ -98,7 +111,7 @@ _rl_with_macro_input (string) /* Return the next character available from a macro, or 0 if there are no macro characters. */ int -_rl_next_macro_key () +_rl_next_macro_key (void) { int c; @@ -117,12 +130,26 @@ _rl_next_macro_key () _rl_pop_executing_macro (); return c; #else + /* XXX - consider doing the same as the callback code, just not testing + whether we're running in callback mode */ return (rl_executing_macro[executing_macro_index++]); #endif } int -_rl_prev_macro_key () +_rl_peek_macro_key (void) +{ + if (rl_executing_macro == 0) + return (0); + if (rl_executing_macro[executing_macro_index] == 0 && (macro_list == 0 || macro_list->string == 0)) + return (0); + if (rl_executing_macro[executing_macro_index] == 0 && macro_list && macro_list->string) + return (macro_list->string[0]); + return (rl_executing_macro[executing_macro_index]); +} + +int +_rl_prev_macro_key (void) { if (rl_executing_macro == 0) return (0); @@ -136,7 +163,7 @@ _rl_prev_macro_key () /* Save the currently executing macro on a stack of saved macros. */ void -_rl_push_executing_macro () +_rl_push_executing_macro (void) { struct saved_macro *saver; @@ -146,12 +173,14 @@ _rl_push_executing_macro () saver->string = rl_executing_macro; macro_list = saver; + + macro_level++; } /* Discard the current macro, replacing it with the one on the top of the stack of saved macros. */ void -_rl_pop_executing_macro () +_rl_pop_executing_macro (void) { struct saved_macro *macro; @@ -168,14 +197,15 @@ _rl_pop_executing_macro () xfree (macro); } + macro_level--; + if (rl_executing_macro == 0) RL_UNSETSTATE(RL_STATE_MACROINPUT); } /* Add a character to the macro being built. */ void -_rl_add_macro_char (c) - int c; +_rl_add_macro_char (int c) { if (current_macro_index + 1 >= current_macro_size) { @@ -190,7 +220,7 @@ _rl_add_macro_char (c) } void -_rl_kill_kbd_macro () +_rl_kill_kbd_macro (void) { if (current_macro) { @@ -213,8 +243,7 @@ _rl_kill_kbd_macro () definition to the end of the existing macro, and start by re-executing the existing macro. */ int -rl_start_kbd_macro (ignore1, ignore2) - int ignore1, ignore2; +rl_start_kbd_macro (int ignore1, int ignore2) { if (RL_ISSTATE (RL_STATE_MACRODEF)) { @@ -238,8 +267,7 @@ rl_start_kbd_macro (ignore1, ignore2) A numeric argument says to execute the macro right now, that many times, counting the definition as the first time. */ int -rl_end_kbd_macro (count, ignore) - int count, ignore; +rl_end_kbd_macro (int count, int ignore) { if (RL_ISSTATE (RL_STATE_MACRODEF) == 0) { @@ -258,8 +286,7 @@ rl_end_kbd_macro (count, ignore) /* Execute the most recently defined keyboard macro. COUNT says how many times to execute it. */ int -rl_call_last_kbd_macro (count, ignore) - int count, ignore; +rl_call_last_kbd_macro (int count, int ignore) { if (current_macro == 0) _rl_abort_internal (); @@ -277,8 +304,7 @@ rl_call_last_kbd_macro (count, ignore) } int -rl_print_last_kbd_macro (count, ignore) - int count, ignore; +rl_print_last_kbd_macro (int count, int ignore) { char *m; @@ -300,8 +326,7 @@ rl_print_last_kbd_macro (count, ignore) } void -rl_push_macro_input (macro) - char *macro; +rl_push_macro_input (char *macro) { _rl_with_macro_input (macro); } diff --git a/lib/readline/mbutil.c b/lib/readline/mbutil.c index 314a49b6..65543416 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-2015 Free Software Foundation, Inc. +/* Copyright (C) 2001-2017 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. @@ -76,9 +76,7 @@ int _rl_utf8locale = 0; #if defined(HANDLE_MULTIBYTE) static int -_rl_find_next_mbchar_internal (string, seed, count, find_non_zero) - char *string; - int seed, count, find_non_zero; +_rl_find_next_mbchar_internal (char *string, int seed, int count, int find_non_zero) { size_t tmp, len; mbstate_t ps; @@ -94,6 +92,11 @@ _rl_find_next_mbchar_internal (string, seed, count, find_non_zero) return seed; point = seed + _rl_adjust_point (string, seed, &ps); + /* if _rl_adjust_point returns -1, the character or string is invalid. + treat as a byte. */ + if (point == seed - 1) /* invalid */ + return seed + 1; + /* if this is true, means that seed was not pointing to a byte indicating the beginning of a multibyte character. Correct the point and consume one char. */ @@ -105,7 +108,14 @@ _rl_find_next_mbchar_internal (string, seed, count, find_non_zero) len = strlen (string + point); if (len == 0) break; - tmp = mbrtowc (&wc, string+point, len, &ps); + if (_rl_utf8locale && UTF8_SINGLEBYTE(string[point])) + { + tmp = 1; + wc = (wchar_t) string[point]; + memset(&ps, 0, sizeof(mbstate_t)); + } + else + tmp = mbrtowc (&wc, string+point, len, &ps); if (MB_INVALIDCH ((size_t)tmp)) { /* invalid bytes. assume a byte represents a character */ @@ -146,9 +156,7 @@ _rl_find_next_mbchar_internal (string, seed, count, find_non_zero) } /*static*/ int -_rl_find_prev_mbchar_internal (string, seed, find_non_zero) - char *string; - int seed, find_non_zero; +_rl_find_prev_mbchar_internal (char *string, int seed, int find_non_zero) { mbstate_t ps; int prev, non_zero_prev, point, length; @@ -166,10 +174,17 @@ _rl_find_prev_mbchar_internal (string, seed, find_non_zero) prev = non_zero_prev = point = 0; while (point < seed) { - tmp = mbrtowc (&wc, string + point, length - point, &ps); + if (_rl_utf8locale && UTF8_SINGLEBYTE(string[point])) + { + tmp = 1; + wc = (wchar_t) string[point]; + memset(&ps, 0, sizeof(mbstate_t)); + } + else + tmp = mbrtowc (&wc, string + point, length - point, &ps); if (MB_INVALIDCH ((size_t)tmp)) { - /* in this case, bytes are invalid or shorted to compose + /* in this case, bytes are invalid or too short to compose multibyte char, so assume that the first byte represents a single character anyway. */ tmp = 1; @@ -206,13 +221,15 @@ _rl_find_prev_mbchar_internal (string, seed, find_non_zero) if an invalid multibyte sequence was encountered. It returns (size_t)(-2) if it couldn't parse a complete multibyte character. */ int -_rl_get_char_len (src, ps) - char *src; - mbstate_t *ps; +_rl_get_char_len (char *src, mbstate_t *ps) { - size_t tmp; + size_t tmp, l; + int mb_cur_max; - tmp = mbrlen((const char *)src, (size_t)strlen (src), ps); + /* Look at no more than MB_CUR_MAX characters */ + l = (size_t)strlen (src); + mb_cur_max = MB_CUR_MAX; + tmp = mbrlen((const char *)src, (l < mb_cur_max) ? l : mb_cur_max, ps); if (tmp == (size_t)(-2)) { /* shorted to compose multibyte char */ @@ -237,13 +254,7 @@ _rl_get_char_len (src, ps) /* compare the specified two characters. If the characters matched, return 1. Otherwise return 0. */ int -_rl_compare_chars (buf1, pos1, ps1, buf2, pos2, ps2) - char *buf1; - int pos1; - mbstate_t *ps1; - char *buf2; - int pos2; - mbstate_t *ps2; +_rl_compare_chars (char *buf1, int pos1, mbstate_t *ps1, char *buf2, int pos2, mbstate_t *ps2) { int i, w1, w2; @@ -263,18 +274,16 @@ _rl_compare_chars (buf1, pos1, ps1, buf2, pos2, ps2) /* adjust pointed byte and find mbstate of the point of string. adjusted point will be point <= adjusted_point, and returns differences of the byte(adjusted_point - point). - if point is invalied (point < 0 || more than string length), + if point is invalid (point < 0 || more than string length), it returns -1 */ int -_rl_adjust_point (string, point, ps) - char *string; - int point; - mbstate_t *ps; +_rl_adjust_point (char *string, int point, mbstate_t *ps) { - size_t tmp = 0; - int length; - int pos = 0; + size_t tmp; + int length, pos; + tmp = 0; + pos = 0; length = strlen(string); if (point < 0) return -1; @@ -283,10 +292,13 @@ _rl_adjust_point (string, point, ps) while (pos < point) { - tmp = mbrlen (string + pos, length - pos, ps); + if (_rl_utf8locale && UTF8_SINGLEBYTE(string[pos])) + tmp = 1; + else + tmp = mbrlen (string + pos, length - pos, ps); if (MB_INVALIDCH ((size_t)tmp)) { - /* in this case, bytes are invalid or shorted to compose + /* in this case, bytes are invalid or too short to compose multibyte char, so assume that the first byte represents a single character anyway. */ pos++; @@ -305,11 +317,7 @@ _rl_adjust_point (string, point, ps) } int -_rl_is_mbchar_matched (string, seed, end, mbchar, length) - char *string; - int seed, end; - char *mbchar; - int length; +_rl_is_mbchar_matched (char *string, int seed, int end, char *mbchar, int length) { int i; @@ -323,9 +331,7 @@ _rl_is_mbchar_matched (string, seed, end, mbchar, length) } wchar_t -_rl_char_value (buf, ind) - char *buf; - int ind; +_rl_char_value (char *buf, int ind) { size_t tmp; wchar_t wc; @@ -334,9 +340,13 @@ _rl_char_value (buf, ind) if (MB_LEN_MAX == 1 || rl_byte_oriented) return ((wchar_t) buf[ind]); + if (_rl_utf8locale && UTF8_SINGLEBYTE(buf[ind])) + return ((wchar_t) buf[ind]); l = strlen (buf); if (ind >= l - 1) return ((wchar_t) buf[ind]); + if (l < ind) /* Sanity check */ + l = strlen (buf+ind); memset (&ps, 0, sizeof (mbstate_t)); tmp = mbrtowc (&wc, buf + ind, l - ind, &ps); if (MB_INVALIDCH (tmp) || MB_NULLWCH (tmp)) @@ -350,9 +360,7 @@ _rl_char_value (buf, ind) characters. */ #undef _rl_find_next_mbchar int -_rl_find_next_mbchar (string, seed, count, flags) - char *string; - int seed, count, flags; +_rl_find_next_mbchar (char *string, int seed, int count, int flags) { #if defined (HANDLE_MULTIBYTE) return _rl_find_next_mbchar_internal (string, seed, count, flags); @@ -366,9 +374,7 @@ _rl_find_next_mbchar (string, seed, count, flags) we look for non-zero-width multibyte characters. */ #undef _rl_find_prev_mbchar int -_rl_find_prev_mbchar (string, seed, flags) - char *string; - int seed, flags; +_rl_find_prev_mbchar (char *string, int seed, int flags) { #if defined (HANDLE_MULTIBYTE) return _rl_find_prev_mbchar_internal (string, seed, flags); diff --git a/lib/readline/misc.c b/lib/readline/misc.c index f7acdee0..64b1457d 100644 --- a/lib/readline/misc.c +++ b/lib/readline/misc.c @@ -1,6 +1,6 @@ /* misc.c -- miscellaneous bindable readline functions. */ -/* Copyright (C) 1987-2015 Free Software Foundation, Inc. +/* Copyright (C) 1987-2017 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. @@ -76,7 +76,7 @@ int _rl_history_saved_point = -1; /* **************************************************************** */ int -_rl_arg_overflow () +_rl_arg_overflow (void) { if (rl_numeric_arg > 1000000) { @@ -92,7 +92,7 @@ _rl_arg_overflow () } void -_rl_arg_init () +_rl_arg_init (void) { rl_save_prompt (); _rl_argcxt = 0; @@ -100,7 +100,7 @@ _rl_arg_init () } int -_rl_arg_getchar () +_rl_arg_getchar (void) { int c; @@ -116,9 +116,7 @@ _rl_arg_getchar () argument should be aborted, 0 if we should not read any more chars, and 1 if we should continue to read chars. */ int -_rl_arg_dispatch (cxt, c) - _rl_arg_cxt cxt; - int c; +_rl_arg_dispatch (_rl_arg_cxt cxt, int c) { int key, r; @@ -193,7 +191,7 @@ _rl_arg_dispatch (cxt, c) /* Handle C-u style numeric args, as well as M--, and M-digits. */ static int -rl_digit_loop () +rl_digit_loop (void) { int c, r; @@ -220,7 +218,7 @@ rl_digit_loop () /* Create a default argument. */ void -_rl_reset_argument () +_rl_reset_argument (void) { rl_numeric_arg = rl_arg_sign = 1; rl_explicit_arg = 0; @@ -229,8 +227,7 @@ _rl_reset_argument () /* Start a numeric argument with initial value KEY */ int -rl_digit_argument (ignore, key) - int ignore, key; +rl_digit_argument (int ignore, int key) { _rl_arg_init (); if (RL_ISSTATE (RL_STATE_CALLBACK)) @@ -250,8 +247,7 @@ rl_digit_argument (ignore, key) Read a key. If the key has nothing to do with arguments, then dispatch on it. If the key is the abort character then abort. */ int -rl_universal_argument (count, key) - int count, key; +rl_universal_argument (int count, int key) { _rl_arg_init (); rl_numeric_arg *= 4; @@ -260,8 +256,7 @@ rl_universal_argument (count, key) } int -_rl_arg_callback (cxt) - _rl_arg_cxt cxt; +_rl_arg_callback (_rl_arg_cxt cxt) { int c, r; @@ -280,12 +275,14 @@ _rl_arg_callback (cxt) } r = _rl_arg_dispatch (cxt, c); + if (r > 0) + rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg); return (r != 1); } /* What to do when you abort reading an argument. */ int -rl_discard_argument () +rl_discard_argument (void) { rl_ding (); rl_clear_message (); @@ -310,7 +307,7 @@ HIST_ENTRY *_rl_saved_line_for_history = (HIST_ENTRY *)NULL; /* Set the history pointer back to the last entry in the history. */ void -_rl_start_using_history () +_rl_start_using_history (void) { using_history (); if (_rl_saved_line_for_history) @@ -321,8 +318,7 @@ _rl_start_using_history () /* Free the contents (and containing structure) of a HIST_ENTRY. */ void -_rl_free_history_entry (entry) - HIST_ENTRY *entry; +_rl_free_history_entry (HIST_ENTRY *entry) { if (entry == 0) return; @@ -335,7 +331,7 @@ _rl_free_history_entry (entry) /* Perhaps put back the current line if it has changed. */ int -rl_maybe_replace_line () +rl_maybe_replace_line (void) { HIST_ENTRY *temp; @@ -353,7 +349,7 @@ rl_maybe_replace_line () /* Restore the _rl_saved_line_for_history if there is one. */ int -rl_maybe_unsave_line () +rl_maybe_unsave_line (void) { if (_rl_saved_line_for_history) { @@ -372,7 +368,7 @@ rl_maybe_unsave_line () /* Save the current line in _rl_saved_line_for_history. */ int -rl_maybe_save_line () +rl_maybe_save_line (void) { if (_rl_saved_line_for_history == 0) { @@ -386,7 +382,7 @@ rl_maybe_save_line () } int -_rl_free_saved_history_line () +_rl_free_saved_history_line (void) { if (_rl_saved_line_for_history) { @@ -397,7 +393,7 @@ _rl_free_saved_history_line () } static void -_rl_history_set_point () +_rl_history_set_point (void) { rl_point = (_rl_history_preserve_point && _rl_history_saved_point != -1) ? _rl_history_saved_point @@ -415,9 +411,7 @@ _rl_history_set_point () } void -rl_replace_from_history (entry, flags) - HIST_ENTRY *entry; - int flags; /* currently unused */ +rl_replace_from_history (HIST_ENTRY *entry, int flags) { /* Can't call with `1' because rl_undo_list might point to an undo list from a history entry, just like we're setting up here. */ @@ -441,7 +435,7 @@ rl_replace_from_history (entry, 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 () +_rl_revert_all_lines (void) { int hpos; HIST_ENTRY *entry; @@ -490,7 +484,7 @@ _rl_revert_all_lines () to an UNDO_LIST * saved as some history entry's data member. This should not be called while editing is active. */ void -rl_clear_history () +rl_clear_history (void) { HIST_ENTRY **hlist, *hent; register int i; @@ -524,16 +518,14 @@ rl_clear_history () /* Meta-< goes to the start of the history. */ int -rl_beginning_of_history (count, key) - int count, key; +rl_beginning_of_history (int count, int key) { return (rl_get_previous_history (1 + where_history (), key)); } /* Meta-> goes to the end of the history. (The current line). */ int -rl_end_of_history (count, key) - int count, key; +rl_end_of_history (int count, int key) { rl_maybe_replace_line (); using_history (); @@ -543,8 +535,7 @@ rl_end_of_history (count, key) /* Move down to the next history line. */ int -rl_get_next_history (count, key) - int count, key; +rl_get_next_history (int count, int key) { HIST_ENTRY *temp; @@ -582,15 +573,14 @@ rl_get_next_history (count, key) /* Get the previous item out of our interactive history, making it the current line. If there is no previous history, just ding. */ int -rl_get_previous_history (count, key) - int count, key; +rl_get_previous_history (int count, int key) { HIST_ENTRY *old_temp, *temp; if (count < 0) return (rl_get_next_history (-count, key)); - if (count == 0) + if (count == 0 || history_list () == 0) return 0; /* either not saved by rl_newline or at end of line, so set appropriately. */ @@ -620,7 +610,10 @@ rl_get_previous_history (count, key) temp = old_temp; if (temp == 0) - rl_ding (); + { + rl_maybe_unsave_line (); + rl_ding (); + } else { rl_replace_from_history (temp, 0); @@ -637,8 +630,7 @@ rl_get_previous_history (count, key) /* **************************************************************** */ /* How to toggle back and forth between editing modes. */ int -rl_vi_editing_mode (count, key) - int count, key; +rl_vi_editing_mode (int count, int key) { #if defined (VI_MODE) _rl_set_insert_mode (RL_IM_INSERT, 1); /* vi mode ignores insert mode */ @@ -650,8 +642,7 @@ rl_vi_editing_mode (count, key) } int -rl_emacs_editing_mode (count, key) - int count, key; +rl_emacs_editing_mode (int count, int key) { rl_editing_mode = emacs_mode; _rl_set_insert_mode (RL_IM_INSERT, 1); /* emacs mode default is insert mode */ @@ -665,8 +656,7 @@ rl_emacs_editing_mode (count, key) /* Function for the rest of the library to use to set insert/overwrite mode. */ void -_rl_set_insert_mode (im, force) - int im, force; +_rl_set_insert_mode (int im, int force) { #ifdef CURSOR_MODE _rl_set_cursor (im, force); @@ -678,8 +668,7 @@ _rl_set_insert_mode (im, force) /* Toggle overwrite mode. A positive explicit argument selects overwrite mode. A negative or zero explicit argument selects insert mode. */ int -rl_overwrite_mode (count, key) - int count, key; +rl_overwrite_mode (int count, int key) { if (rl_explicit_arg == 0) _rl_set_insert_mode (rl_insert_mode ^ 1, 0); diff --git a/lib/readline/nls.c b/lib/readline/nls.c index d3b36344..d2f67e0d 100644 --- a/lib/readline/nls.c +++ b/lib/readline/nls.c @@ -1,6 +1,6 @@ /* nls.c -- skeletal internationalization code. */ -/* Copyright (C) 1996-2009 Free Software Foundation, Inc. +/* Copyright (C) 1996-2017 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. @@ -74,6 +74,7 @@ static char *legal_lang_values[] = "iso88599", "iso885910", "koi8r", + "utf8", 0 }; @@ -85,8 +86,7 @@ static char *find_codeset PARAMS((char *, size_t *)); static char *_rl_get_locale_var PARAMS((const char *)); static char * -_rl_get_locale_var (v) - const char *v; +_rl_get_locale_var (const char *v) { char *lspec; @@ -100,8 +100,7 @@ _rl_get_locale_var (v) } static int -utf8locale (lspec) - char *lspec; +utf8locale (char *lspec) { char *cp; size_t len; @@ -118,16 +117,12 @@ utf8locale (lspec) #endif } -/* Check for LC_ALL, LC_CTYPE, and LANG and use the first with a value - to decide the defaults for 8-bit character input and output. Returns - 1 if we set eight-bit mode. */ -int -_rl_init_eightbit () +/* Query the right environment variables and call setlocale() to initialize + the C library locale settings. */ +char * +_rl_init_locale (void) { -/* If we have setlocale(3), just check the current LC_CTYPE category - value, and go into eight-bit mode if it's not C or POSIX. */ -#if defined (HAVE_SETLOCALE) - char *lspec, *t; + char *ret, *lspec; /* Set the LC_CTYPE locale category from environment variables. */ lspec = _rl_get_locale_var ("LC_CTYPE"); @@ -140,10 +135,25 @@ _rl_init_eightbit () lspec = setlocale (LC_CTYPE, (char *)NULL); if (lspec == 0) lspec = ""; - t = setlocale (LC_CTYPE, lspec); + ret = setlocale (LC_CTYPE, lspec); /* ok, since it does not change locale */ + + _rl_utf8locale = (ret && *ret) ? utf8locale (ret) : 0; + + return ret; +} + +/* Check for LC_ALL, LC_CTYPE, and LANG and use the first with a value + to decide the defaults for 8-bit character input and output. Returns + 1 if we set eight-bit mode. */ +int +_rl_init_eightbit (void) +{ +/* If we have setlocale(3), just check the current LC_CTYPE category + value, and go into eight-bit mode if it's not C or POSIX. */ +#if defined (HAVE_SETLOCALE) + char *lspec, *t; - if (t && *t) - _rl_utf8locale = utf8locale (t); + t = _rl_init_locale (); /* returns static pointer */ if (t && *t && (t[0] != 'C' || t[1]) && (STREQ (t, "POSIX") == 0)) { @@ -174,16 +184,17 @@ _rl_init_eightbit () _rl_output_meta_chars = 1; break; } + + _rl_utf8locale = *t ? STREQ (t, "utf8") : 0; + xfree (t); return (legal_lang_values[i] ? 1 : 0); - #endif /* !HAVE_SETLOCALE */ } #if !defined (HAVE_SETLOCALE) static char * -normalize_codeset (codeset) - char *codeset; +normalize_codeset (char *codeset) { size_t namelen, i; int len, all_digits; @@ -230,9 +241,7 @@ normalize_codeset (codeset) /* Isolate codeset portion of locale specification. */ static char * -find_codeset (name, lenp) - char *name; - size_t *lenp; +find_codeset (char *name, size_t *lenp) { char *cp, *language, *result; diff --git a/lib/readline/parens.c b/lib/readline/parens.c index ecc465c0..af479773 100644 --- a/lib/readline/parens.c +++ b/lib/readline/parens.c @@ -1,6 +1,6 @@ /* parens.c -- implementation of matching parentheses feature. */ -/* Copyright (C) 1987, 1989, 1992-2015 Free Software Foundation, Inc. +/* Copyright (C) 1987, 1989, 1992-2015, 2017 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. @@ -64,8 +64,7 @@ static int _paren_blink_usec = 500000; /* Change emacs_standard_keymap to have bindings for paren matching when ON_OR_OFF is 1, change them back to self_insert when ON_OR_OFF == 0. */ void -_rl_enable_paren_matching (on_or_off) - int on_or_off; +_rl_enable_paren_matching (int on_or_off) { if (on_or_off) { @@ -98,8 +97,7 @@ _rl_enable_paren_matching (on_or_off) } int -rl_set_paren_blink_timeout (u) - int u; +rl_set_paren_blink_timeout (int u) { int o; @@ -110,8 +108,7 @@ rl_set_paren_blink_timeout (u) } int -rl_insert_close (count, invoking_key) - int count, invoking_key; +rl_insert_close (int count, int invoking_key) { if (rl_explicit_arg || !rl_blink_matching_paren) _rl_insert_char (count, invoking_key); @@ -148,9 +145,7 @@ rl_insert_close (count, invoking_key) } static int -find_matching_open (string, from, closer) - char *string; - int from, closer; +find_matching_open (char *string, int from, int closer) { register int i; int opener, level, delimiter; diff --git a/lib/readline/parse-colors.c b/lib/readline/parse-colors.c index 98b2e9d1..05ec9bc3 100644 --- a/lib/readline/parse-colors.c +++ b/lib/readline/parse-colors.c @@ -2,8 +2,8 @@ Modified by Chet Ramey for Readline. - Copyright (C) 1985, 1988, 1990-1991, 1995-2010, 2012 Free Software Foundation, - Inc. + Copyright (C) 1985, 1988, 1990-1991, 1995-2010, 2012, 2017 + 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 @@ -297,7 +297,7 @@ get_funky_string (char **dest, const char **src, bool equals_end, size_t *output } #endif /* COLOR_SUPPORT */ -void _rl_parse_colors() +void _rl_parse_colors(void) { #if defined (COLOR_SUPPORT) const char *p; /* Pointer to character being parsed */ diff --git a/lib/readline/readline.c b/lib/readline/readline.c index e51df4f0..4842a02e 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-2016 Free Software Foundation, Inc. +/* Copyright (C) 1987-2017 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. @@ -242,7 +242,7 @@ int rl_erase_empty_line = 0; /* Non-zero means to read only this many characters rather than up to a character bound to accept-line. */ -int rl_num_chars_to_read; +int rl_num_chars_to_read = 0; /* Line buffer and maintenance. */ char *rl_line_buffer = (char *)NULL; @@ -325,8 +325,7 @@ int _rl_meta_flag = 0; /* Forward declaration */ /* Set up the prompt and expand it. Called from readline() and rl_callback_handler_install (). */ int -rl_set_prompt (prompt) - const char *prompt; +rl_set_prompt (const char *prompt) { FREE (rl_prompt); rl_prompt = prompt ? savestring (prompt) : (char *)NULL; @@ -339,8 +338,7 @@ rl_set_prompt (prompt) /* Read a line of input. Prompt with PROMPT. An empty PROMPT means none. A return value of NULL means that EOF was encountered. */ char * -readline (prompt) - const char *prompt; +readline (const char *prompt) { char *value; #if 0 @@ -401,7 +399,7 @@ readline (prompt) #endif STATIC_CALLBACK void -readline_internal_setup () +readline_internal_setup (void) { char *nprompt; @@ -419,7 +417,10 @@ readline_internal_setup () #if defined (VI_MODE) if (rl_editing_mode == vi_mode) rl_vi_insertion_mode (1, 'i'); /* don't want to reset last */ + else #endif /* VI_MODE */ + if (_rl_show_mode_in_prompt) + _rl_reset_prompt (); /* If we're not echoing, we still want to at least print a prompt, because rl_redisplay will not do it for us. If the calling application has a @@ -450,8 +451,7 @@ readline_internal_setup () } STATIC_CALLBACK char * -readline_internal_teardown (eof) - int eof; +readline_internal_teardown (int eof) { char *temp; HIST_ENTRY *entry; @@ -493,7 +493,7 @@ readline_internal_teardown (eof) } void -_rl_internal_char_cleanup () +_rl_internal_char_cleanup (void) { #if defined (VI_MODE) /* In vi mode, when you exit insert mode, the cursor moves back @@ -524,13 +524,13 @@ _rl_internal_char_cleanup () STATIC_CALLBACK int #if defined (READLINE_CALLBACKS) -readline_internal_char () +readline_internal_char (void) #else -readline_internal_charloop () +readline_internal_charloop (void) #endif { static int lastc, eof_found; - int c, code, lk; + int c, code, lk, r; lastc = EOF; @@ -626,7 +626,7 @@ readline_internal_charloop () } lastc = c; - _rl_dispatch ((unsigned char)c, _rl_keymap); + r = _rl_dispatch ((unsigned char)c, _rl_keymap); RL_CHECK_SIGNALS (); /* If there was no change in _rl_last_command_was_kill, then no kill @@ -648,7 +648,7 @@ readline_internal_charloop () #if defined (READLINE_CALLBACKS) static int -readline_internal_charloop () +readline_internal_charloop (void) { int eof = 1; @@ -662,7 +662,7 @@ readline_internal_charloop () the global rl_outstream. If rl_prompt is non-null, then that is our prompt. */ static char * -readline_internal () +readline_internal (void) { int eof; @@ -672,7 +672,7 @@ readline_internal () } void -_rl_init_line_state () +_rl_init_line_state (void) { rl_point = rl_end = rl_mark = 0; the_line = rl_line_buffer; @@ -680,14 +680,14 @@ _rl_init_line_state () } void -_rl_set_the_line () +_rl_set_the_line (void) { the_line = rl_line_buffer; } #if defined (READLINE_CALLBACKS) _rl_keyseq_cxt * -_rl_keyseq_cxt_alloc () +_rl_keyseq_cxt_alloc (void) { _rl_keyseq_cxt *cxt; @@ -703,14 +703,13 @@ _rl_keyseq_cxt_alloc () } void -_rl_keyseq_cxt_dispose (cxt) - _rl_keyseq_cxt *cxt; +_rl_keyseq_cxt_dispose (_rl_keyseq_cxt *cxt) { xfree (cxt); } void -_rl_keyseq_chain_dispose () +_rl_keyseq_chain_dispose (void) { _rl_keyseq_cxt *cxt; @@ -724,8 +723,7 @@ _rl_keyseq_chain_dispose () #endif static int -_rl_subseq_getchar (key) - int key; +_rl_subseq_getchar (int key) { int k; @@ -742,8 +740,7 @@ _rl_subseq_getchar (key) #if defined (READLINE_CALLBACKS) int -_rl_dispatch_callback (cxt) - _rl_keyseq_cxt *cxt; +_rl_dispatch_callback (_rl_keyseq_cxt *cxt) { int nkey, r; @@ -794,19 +791,14 @@ _rl_dispatch_callback (cxt) If the associated command is really a keymap, then read another key, and dispatch into that map. */ int -_rl_dispatch (key, map) - register int key; - Keymap map; +_rl_dispatch (register int key, Keymap map) { _rl_dispatching_keymap = map; return _rl_dispatch_subseq (key, map, 0); } int -_rl_dispatch_subseq (key, map, got_subseq) - register int key; - Keymap map; - int got_subseq; +_rl_dispatch_subseq (register int key, Keymap map, int got_subseq) { int r, newkey; char *macro; @@ -920,6 +912,15 @@ _rl_dispatch_subseq (key, map, got_subseq) _rl_pushed_input_available () == 0 && _rl_input_queued ((_rl_keyseq_timeout > 0) ? _rl_keyseq_timeout*1000 : 0) == 0) return (_rl_dispatch (ANYOTHERKEY, FUNCTION_TO_KEYMAP (map, key))); + /* This is a very specific test. It can possibly be generalized in + the future, but for now it handles a specific case of ESC being + the last character in a keyboard macro. */ + if (rl_editing_mode == vi_mode && key == ESC && map == vi_insertion_keymap && + (RL_ISSTATE (RL_STATE_INPUTPENDING) == 0) && + (RL_ISSTATE (RL_STATE_MACROINPUT) && _rl_peek_macro_key () == 0) && + _rl_pushed_input_available () == 0 && + _rl_input_queued ((_rl_keyseq_timeout > 0) ? _rl_keyseq_timeout*1000 : 0) == 0) + return (_rl_dispatch (ANYOTHERKEY, FUNCTION_TO_KEYMAP (map, key))); #endif RESIZE_KEYSEQ_BUFFER (); @@ -1014,10 +1015,7 @@ _rl_dispatch_subseq (key, map, got_subseq) } static int -_rl_subseq_result (r, map, key, got_subseq) - int r; - Keymap map; - int key, got_subseq; +_rl_subseq_result (int r, Keymap map, int key, int got_subseq) { Keymap m; int type, nt; @@ -1069,7 +1067,7 @@ _rl_subseq_result (r, map, key, got_subseq) _rl_dispatching_keymap = map; return -2; } - else if (r && got_subseq) + else if (r < 0 && got_subseq) /* XXX */ { /* OK, back up the chain. */ if (RL_ISSTATE (RL_STATE_MACROINPUT)) @@ -1091,11 +1089,11 @@ _rl_subseq_result (r, map, key, got_subseq) /* Initialize readline (and terminal if not already). */ int -rl_initialize () +rl_initialize (void) { /* If we have never been called before, initialize the terminal and data structures. */ - if (!rl_initialized) + if (rl_initialized == 0) { RL_SETSTATE(RL_STATE_INITIALIZING); readline_initialize_everything (); @@ -1103,6 +1101,8 @@ rl_initialize () rl_initialized++; RL_SETSTATE(RL_STATE_INITIALIZED); } + else + (void)_rl_init_locale (); /* check current locale */ /* Initialize the current line information. */ _rl_init_line_state (); @@ -1137,7 +1137,7 @@ rl_initialize () #if 0 #if defined (__EMX__) static void -_emx_build_environ () +_emx_build_environ (void) { TIB *tibp; PIB *pibp; @@ -1162,7 +1162,7 @@ _emx_build_environ () /* Initialize the entire state of the world. */ static void -readline_initialize_everything () +readline_initialize_everything (void) { #if 0 #if defined (__EMX__) @@ -1247,7 +1247,7 @@ readline_initialize_everything () input editing characters, then bind them to their readline equivalents, iff the characters are not bound to keymaps. */ static void -readline_default_bindings () +readline_default_bindings (void) { if (_rl_bind_stty_chars) rl_tty_set_default_bindings (_rl_keymap); @@ -1256,7 +1256,7 @@ readline_default_bindings () /* Reset the default bindings for the terminal special characters we're interested in back to rl_insert and read the new ones. */ static void -reset_default_bindings () +reset_default_bindings (void) { if (_rl_bind_stty_chars) { @@ -1267,8 +1267,7 @@ reset_default_bindings () /* Bind some common arrow key sequences in MAP. */ static void -bind_arrow_keys_internal (map) - Keymap map; +bind_arrow_keys_internal (Keymap map) { Keymap xkeymap; @@ -1296,6 +1295,15 @@ bind_arrow_keys_internal (map) rl_bind_keyseq_if_unbound ("\033OH", rl_beg_of_line); rl_bind_keyseq_if_unbound ("\033OF", rl_end_of_line); + /* Key bindings for control-arrow keys */ + rl_bind_keyseq_if_unbound ("\033[1;5C", rl_forward_word); + rl_bind_keyseq_if_unbound ("\033[1;5D", rl_backward_word); + rl_bind_keyseq_if_unbound ("\033[3;5~", rl_kill_word); + + /* Key bindings for alt-arrow keys */ + rl_bind_keyseq_if_unbound ("\033[1;3C", rl_forward_word); + rl_bind_keyseq_if_unbound ("\033[1;3D", rl_backward_word); + #if defined (__MINGW32__) rl_bind_keyseq_if_unbound ("\340H", rl_get_previous_history); rl_bind_keyseq_if_unbound ("\340P", rl_get_next_history); @@ -1324,7 +1332,7 @@ bind_arrow_keys_internal (map) the inputrc file a chance to bind them and create `real' keymaps for the arrow key prefix. */ static void -bind_arrow_keys () +bind_arrow_keys (void) { bind_arrow_keys_internal (emacs_standard_keymap); @@ -1339,7 +1347,7 @@ bind_arrow_keys () } static void -bind_bracketed_paste_prefix () +bind_bracketed_paste_prefix (void) { Keymap xkeymap; @@ -1361,8 +1369,7 @@ bind_bracketed_paste_prefix () /* **************************************************************** */ int -rl_save_state (sp) - struct readline_state *sp; +rl_save_state (struct readline_state *sp) { if (sp == 0) return -1; @@ -1402,8 +1409,7 @@ rl_save_state (sp) } int -rl_restore_state (sp) - struct readline_state *sp; +rl_restore_state (struct readline_state *sp) { if (sp == 0) return -1; diff --git a/lib/readline/readline.c.orig b/lib/readline/readline.c.orig deleted file mode 100644 index 55c0522e..00000000 --- a/lib/readline/readline.c.orig +++ /dev/null @@ -1,1364 +0,0 @@ -/* readline.c -- a general facility for reading lines of input - with emacs style editing and completion. */ - -/* Copyright (C) 1987-2013 Free Software Foundation, Inc. - - This file is part of the GNU Readline Library (Readline), a library - for reading lines of text with interactive input and history editing. - - Readline is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Readline is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Readline. If not, see <http://www.gnu.org/licenses/>. -*/ - -#define READLINE_LIBRARY - -#if defined (HAVE_CONFIG_H) -# include <config.h> -#endif - -#include <sys/types.h> -#include "posixstat.h" -#include <fcntl.h> -#if defined (HAVE_SYS_FILE_H) -# include <sys/file.h> -#endif /* HAVE_SYS_FILE_H */ - -#if defined (HAVE_UNISTD_H) -# include <unistd.h> -#endif /* HAVE_UNISTD_H */ - -#if defined (HAVE_STDLIB_H) -# include <stdlib.h> -#else -# include "ansi_stdlib.h" -#endif /* HAVE_STDLIB_H */ - -#if defined (HAVE_LOCALE_H) -# include <locale.h> -#endif - -#include <stdio.h> -#include "posixjmp.h" -#include <errno.h> - -#if !defined (errno) -extern int errno; -#endif /* !errno */ - -/* System-specific feature definitions and include files. */ -#include "rldefs.h" -#include "rlmbutil.h" - -#if defined (__EMX__) -# define INCL_DOSPROCESS -# include <os2.h> -#endif /* __EMX__ */ - -/* Some standard library routines. */ -#include "readline.h" -#include "history.h" - -#include "rlprivate.h" -#include "rlshell.h" -#include "xmalloc.h" - -#ifndef RL_LIBRARY_VERSION -# define RL_LIBRARY_VERSION "5.1" -#endif - -#ifndef RL_READLINE_VERSION -# define RL_READLINE_VERSION 0x0501 -#endif - -extern void _rl_free_history_entry PARAMS((HIST_ENTRY *)); - -#if defined (COLOR_SUPPORT) -extern void _rl_parse_colors PARAMS((void)); /* XXX */ -#endif - - -/* Forward declarations used in this file. */ -static char *readline_internal PARAMS((void)); -static void readline_initialize_everything PARAMS((void)); - -static void bind_arrow_keys_internal PARAMS((Keymap)); -static void bind_arrow_keys PARAMS((void)); - -static void readline_default_bindings PARAMS((void)); -static void reset_default_bindings PARAMS((void)); - -static int _rl_subseq_result PARAMS((int, Keymap, int, int)); -static int _rl_subseq_getchar PARAMS((int)); - -/* **************************************************************** */ -/* */ -/* Line editing input utility */ -/* */ -/* **************************************************************** */ - -const char *rl_library_version = RL_LIBRARY_VERSION; - -int rl_readline_version = RL_READLINE_VERSION; - -/* True if this is `real' readline as opposed to some stub substitute. */ -int rl_gnu_readline_p = 1; - -/* A pointer to the keymap that is currently in use. - By default, it is the standard emacs keymap. */ -Keymap _rl_keymap = emacs_standard_keymap; - -/* The current style of editing. */ -int rl_editing_mode = emacs_mode; - -/* The current insert mode: input (the default) or overwrite */ -int rl_insert_mode = RL_IM_DEFAULT; - -/* Non-zero if we called this function from _rl_dispatch(). It's present - so functions can find out whether they were called from a key binding - or directly from an application. */ -int rl_dispatching; - -/* Non-zero if the previous command was a kill command. */ -int _rl_last_command_was_kill = 0; - -/* The current value of the numeric argument specified by the user. */ -int rl_numeric_arg = 1; - -/* Non-zero if an argument was typed. */ -int rl_explicit_arg = 0; - -/* Temporary value used while generating the argument. */ -int rl_arg_sign = 1; - -/* Non-zero means we have been called at least once before. */ -static int rl_initialized; - -#if 0 -/* If non-zero, this program is running in an EMACS buffer. */ -static int running_in_emacs; -#endif - -/* Flags word encapsulating the current readline state. */ -int rl_readline_state = RL_STATE_NONE; - -/* The current offset in the current input line. */ -int rl_point; - -/* Mark in the current input line. */ -int rl_mark; - -/* Length of the current input line. */ -int rl_end; - -/* Make this non-zero to return the current input_line. */ -int rl_done; - -/* The last function executed by readline. */ -rl_command_func_t *rl_last_func = (rl_command_func_t *)NULL; - -/* Top level environment for readline_internal (). */ -procenv_t _rl_top_level; - -/* The streams we interact with. */ -FILE *_rl_in_stream, *_rl_out_stream; - -/* The names of the streams that we do input and output to. */ -FILE *rl_instream = (FILE *)NULL; -FILE *rl_outstream = (FILE *)NULL; - -/* Non-zero means echo characters as they are read. Defaults to no echo; - set to 1 if there is a controlling terminal, we can get its attributes, - and the attributes include `echo'. Look at rltty.c:prepare_terminal_settings - for the code that sets it. */ -int _rl_echoing_p = 0; - -/* Current prompt. */ -char *rl_prompt = (char *)NULL; -int rl_visible_prompt_length = 0; - -/* Set to non-zero by calling application if it has already printed rl_prompt - and does not want readline to do it the first time. */ -int rl_already_prompted = 0; - -/* The number of characters read in order to type this complete command. */ -int rl_key_sequence_length = 0; - -/* If non-zero, then this is the address of a function to call just - before readline_internal_setup () prints the first prompt. */ -rl_hook_func_t *rl_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. */ -rl_hook_func_t *rl_pre_input_hook = (rl_hook_func_t *)NULL; - -/* What we use internally. You should always refer to RL_LINE_BUFFER. */ -static char *the_line; - -/* The character that can generate an EOF. Really read from - the terminal driver... just defaulted here. */ -int _rl_eof_char = CTRL ('D'); - -/* Non-zero makes this the next keystroke to read. */ -int rl_pending_input = 0; - -/* Pointer to a useful terminal name. */ -const char *rl_terminal_name = (const char *)NULL; - -/* Non-zero means to always use horizontal scrolling in line display. */ -int _rl_horizontal_scroll_mode = 0; - -/* Non-zero means to display an asterisk at the starts of history lines - which have been modified. */ -int _rl_mark_modified_lines = 0; - -/* The style of `bell' notification preferred. This can be set to NO_BELL, - AUDIBLE_BELL, or VISIBLE_BELL. */ -int _rl_bell_preference = AUDIBLE_BELL; - -/* String inserted into the line by rl_insert_comment (). */ -char *_rl_comment_begin; - -/* Keymap holding the function currently being executed. */ -Keymap rl_executing_keymap; - -/* Keymap we're currently using to dispatch. */ -Keymap _rl_dispatching_keymap; - -/* Non-zero means to erase entire line, including prompt, on empty input lines. */ -int rl_erase_empty_line = 0; - -/* Non-zero means to read only this many characters rather than up to a - character bound to accept-line. */ -int rl_num_chars_to_read; - -/* Line buffer and maintenance. */ -char *rl_line_buffer = (char *)NULL; -int rl_line_buffer_len = 0; - -/* Key sequence `contexts' */ -_rl_keyseq_cxt *_rl_kscxt = 0; - -int rl_executing_key; -char *rl_executing_keyseq = 0; -int _rl_executing_keyseq_size = 0; - -/* Timeout (specified in milliseconds) when reading characters making up an - ambiguous multiple-key sequence */ -int _rl_keyseq_timeout = 500; - -#define RESIZE_KEYSEQ_BUFFER() \ - do \ - { \ - if (rl_key_sequence_length + 2 >= _rl_executing_keyseq_size) \ - { \ - _rl_executing_keyseq_size += 16; \ - rl_executing_keyseq = xrealloc (rl_executing_keyseq, _rl_executing_keyseq_size); \ - } \ - } \ - while (0); - -/* Forward declarations used by the display, termcap, and history code. */ - -/* **************************************************************** */ -/* */ -/* `Forward' declarations */ -/* */ -/* **************************************************************** */ - -/* Non-zero means do not parse any lines other than comments and - parser directives. */ -unsigned char _rl_parsing_conditionalized_out = 0; - -/* Non-zero means to convert characters with the meta bit set to - escape-prefixed characters so we can indirect through - emacs_meta_keymap or vi_escape_keymap. */ -int _rl_convert_meta_chars_to_ascii = 1; - -/* Non-zero means to output characters with the meta bit set directly - rather than as a meta-prefixed escape sequence. */ -int _rl_output_meta_chars = 0; - -/* Non-zero means to look at the termios special characters and bind - them to equivalent readline functions at startup. */ -int _rl_bind_stty_chars = 1; - -/* Non-zero means to go through the history list at every newline (or - whenever rl_done is set and readline returns) and revert each line to - its initial state. */ -int _rl_revert_all_at_newline = 0; - -/* Non-zero means to honor the termios ECHOCTL bit and echo control - characters corresponding to keyboard-generated signals. */ -int _rl_echo_control_chars = 1; - -/* Non-zero means to prefix the displayed prompt with a character indicating - the editing mode: @ for emacs, : for vi-command, + for vi-insert. */ -int _rl_show_mode_in_prompt = 0; - -/* **************************************************************** */ -/* */ -/* Top Level Functions */ -/* */ -/* **************************************************************** */ - -/* Non-zero means treat 0200 bit in terminal input as Meta bit. */ -int _rl_meta_flag = 0; /* Forward declaration */ - -/* Set up the prompt and expand it. Called from readline() and - rl_callback_handler_install (). */ -int -rl_set_prompt (prompt) - const char *prompt; -{ - FREE (rl_prompt); - rl_prompt = prompt ? savestring (prompt) : (char *)NULL; - rl_display_prompt = rl_prompt ? rl_prompt : ""; - - rl_visible_prompt_length = rl_expand_prompt (rl_prompt); - return 0; -} - -/* Read a line of input. Prompt with PROMPT. An empty PROMPT means - none. A return value of NULL means that EOF was encountered. */ -char * -readline (prompt) - const char *prompt; -{ - char *value; -#if 0 - int in_callback; -#endif - - /* If we are at EOF return a NULL string. */ - if (rl_pending_input == EOF) - { - rl_clear_pending_input (); - return ((char *)NULL); - } - -#if 0 - /* If readline() is called after installing a callback handler, temporarily - turn off the callback state to avoid ensuing messiness. Patch supplied - by the gdb folks. XXX -- disabled. This can be fooled and readline - left in a strange state by a poorly-timed longjmp. */ - if (in_callback = RL_ISSTATE (RL_STATE_CALLBACK)) - RL_UNSETSTATE (RL_STATE_CALLBACK); -#endif - - rl_set_prompt (prompt); - - rl_initialize (); - if (rl_prep_term_function) - (*rl_prep_term_function) (_rl_meta_flag); - -#if defined (HANDLE_SIGNALS) - rl_set_signals (); -#endif - - value = readline_internal (); - if (rl_deprep_term_function) - (*rl_deprep_term_function) (); - -#if defined (HANDLE_SIGNALS) - rl_clear_signals (); -#endif - -#if 0 - if (in_callback) - RL_SETSTATE (RL_STATE_CALLBACK); -#endif - -#if HAVE_DECL_AUDIT_TTY && defined (ENABLE_TTY_AUDIT_SUPPORT) - if (value) - _rl_audit_tty (value); -#endif - - return (value); -} - -#if defined (READLINE_CALLBACKS) -# define STATIC_CALLBACK -#else -# define STATIC_CALLBACK static -#endif - -STATIC_CALLBACK void -readline_internal_setup () -{ - char *nprompt; - - _rl_in_stream = rl_instream; - _rl_out_stream = rl_outstream; - - /* Enable the meta key only for the duration of readline(), if this - terminal has one and the terminal has been initialized */ - if (_rl_enable_meta & RL_ISSTATE (RL_STATE_TERMPREPPED)) - _rl_enable_meta_key (); - - if (rl_startup_hook) - (*rl_startup_hook) (); - -#if defined (VI_MODE) - if (rl_editing_mode == vi_mode) - rl_vi_insertion_mode (1, 'i'); /* don't want to reset last */ -#endif /* VI_MODE */ - - /* If we're not echoing, we still want to at least print a prompt, because - rl_redisplay will not do it for us. If the calling application has a - custom redisplay function, though, let that function handle it. */ - if (_rl_echoing_p == 0 && rl_redisplay_function == rl_redisplay) - { - if (rl_prompt && rl_already_prompted == 0) - { - nprompt = _rl_strip_prompt (rl_prompt); - fprintf (_rl_out_stream, "%s", nprompt); - fflush (_rl_out_stream); - xfree (nprompt); - } - } - else - { - if (rl_prompt && rl_already_prompted) - rl_on_new_line_with_prompt (); - else - rl_on_new_line (); - (*rl_redisplay_function) (); - } - - if (rl_pre_input_hook) - (*rl_pre_input_hook) (); - - RL_CHECK_SIGNALS (); -} - -STATIC_CALLBACK char * -readline_internal_teardown (eof) - int eof; -{ - char *temp; - HIST_ENTRY *entry; - - RL_CHECK_SIGNALS (); - - /* Restore the original of this history line, iff the line that we - are editing was originally in the history, AND the line has changed. */ - entry = current_history (); - - if (entry && rl_undo_list) - { - temp = savestring (the_line); - rl_revert_line (1, 0); - entry = replace_history_entry (where_history (), the_line, (histdata_t)NULL); - _rl_free_history_entry (entry); - - strcpy (the_line, temp); - xfree (temp); - } - - if (_rl_revert_all_at_newline) - _rl_revert_all_lines (); - - /* At any rate, it is highly likely that this line has an undo list. Get - rid of it now. */ - if (rl_undo_list) - rl_free_undo_list (); - - /* Disable the meta key, if this terminal has one and we were told to use it. - The check whether or not we sent the enable string is in - _rl_disable_meta_key(); the flag is set in _rl_enable_meta_key */ - _rl_disable_meta_key (); - - /* Restore normal cursor, if available. */ - _rl_set_insert_mode (RL_IM_INSERT, 0); - - return (eof ? (char *)NULL : savestring (the_line)); -} - -void -_rl_internal_char_cleanup () -{ -#if defined (VI_MODE) - /* In vi mode, when you exit insert mode, the cursor moves back - over the previous character. We explicitly check for that here. */ - if (rl_editing_mode == vi_mode && _rl_keymap == vi_movement_keymap) - rl_vi_check (); -#endif /* VI_MODE */ - - if (rl_num_chars_to_read && rl_end >= rl_num_chars_to_read) - { - (*rl_redisplay_function) (); - _rl_want_redisplay = 0; - rl_newline (1, '\n'); - } - - if (rl_done == 0) - { - (*rl_redisplay_function) (); - _rl_want_redisplay = 0; - } - - /* If the application writer has told us to erase the entire line if - the only character typed was something bound to rl_newline, do so. */ - if (rl_erase_empty_line && rl_done && rl_last_func == rl_newline && - rl_point == 0 && rl_end == 0) - _rl_erase_entire_line (); -} - -STATIC_CALLBACK int -#if defined (READLINE_CALLBACKS) -readline_internal_char () -#else -readline_internal_charloop () -#endif -{ - static int lastc, eof_found; - int c, code, lk; - - lastc = -1; - eof_found = 0; - -#if !defined (READLINE_CALLBACKS) - while (rl_done == 0) - { -#endif - lk = _rl_last_command_was_kill; - -#if defined (HAVE_POSIX_SIGSETJMP) - code = sigsetjmp (_rl_top_level, 0); -#else - code = setjmp (_rl_top_level); -#endif - - if (code) - { - (*rl_redisplay_function) (); - _rl_want_redisplay = 0; - /* If we get here, we're not being called from something dispatched - from _rl_callback_read_char(), which sets up its own value of - _rl_top_level (saving and restoring the old, of course), so - we can just return here. */ - if (RL_ISSTATE (RL_STATE_CALLBACK)) - return (0); - } - - if (rl_pending_input == 0) - { - /* Then initialize the argument and number of keys read. */ - _rl_reset_argument (); - rl_key_sequence_length = 0; - rl_executing_keyseq[0] = 0; - } - - RL_SETSTATE(RL_STATE_READCMD); - c = rl_read_key (); - RL_UNSETSTATE(RL_STATE_READCMD); - - /* look at input.c:rl_getc() for the circumstances under which this will - be returned; punt immediately on read error without converting it to - a newline; assume that rl_read_key has already called the signal - handler. */ - if (c == READERR) - { -#if defined (READLINE_CALLBACKS) - RL_SETSTATE(RL_STATE_DONE); - return (rl_done = 1); -#else - eof_found = 1; - break; -#endif - } - - /* EOF typed to a non-blank line is a <NL>. If we want to change this, - to force any existing line to be ignored when read(2) reads EOF, - for example, this is the place to change. */ - if (c == EOF && rl_end) - c = NEWLINE; - - /* The character _rl_eof_char typed to blank line, and not as the - previous character is interpreted as EOF. */ - if (((c == _rl_eof_char && lastc != c) || c == EOF) && !rl_end) - { -#if defined (READLINE_CALLBACKS) - RL_SETSTATE(RL_STATE_DONE); - return (rl_done = 1); -#else - eof_found = 1; - break; -#endif - } - - lastc = c; - _rl_dispatch ((unsigned char)c, _rl_keymap); - 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; - - _rl_internal_char_cleanup (); - -#if defined (READLINE_CALLBACKS) - return 0; -#else - } - - return (eof_found); -#endif -} - -#if defined (READLINE_CALLBACKS) -static int -readline_internal_charloop () -{ - int eof = 1; - - while (rl_done == 0) - eof = readline_internal_char (); - return (eof); -} -#endif /* READLINE_CALLBACKS */ - -/* Read a line of input from the global rl_instream, doing output on - the global rl_outstream. - If rl_prompt is non-null, then that is our prompt. */ -static char * -readline_internal () -{ - int eof; - - readline_internal_setup (); - eof = readline_internal_charloop (); - return (readline_internal_teardown (eof)); -} - -void -_rl_init_line_state () -{ - rl_point = rl_end = rl_mark = 0; - the_line = rl_line_buffer; - the_line[0] = 0; -} - -void -_rl_set_the_line () -{ - the_line = rl_line_buffer; -} - -#if defined (READLINE_CALLBACKS) -_rl_keyseq_cxt * -_rl_keyseq_cxt_alloc () -{ - _rl_keyseq_cxt *cxt; - - cxt = (_rl_keyseq_cxt *)xmalloc (sizeof (_rl_keyseq_cxt)); - - cxt->flags = cxt->subseq_arg = cxt->subseq_retval = 0; - - cxt->okey = 0; - cxt->ocxt = _rl_kscxt; - cxt->childval = 42; /* sentinel value */ - - return cxt; -} - -void -_rl_keyseq_cxt_dispose (cxt) - _rl_keyseq_cxt *cxt; -{ - xfree (cxt); -} - -void -_rl_keyseq_chain_dispose () -{ - _rl_keyseq_cxt *cxt; - - while (_rl_kscxt) - { - cxt = _rl_kscxt; - _rl_kscxt = _rl_kscxt->ocxt; - _rl_keyseq_cxt_dispose (cxt); - } -} -#endif - -static int -_rl_subseq_getchar (key) - int key; -{ - int k; - - if (key == ESC) - RL_SETSTATE(RL_STATE_METANEXT); - RL_SETSTATE(RL_STATE_MOREINPUT); - k = rl_read_key (); - RL_UNSETSTATE(RL_STATE_MOREINPUT); - if (key == ESC) - RL_UNSETSTATE(RL_STATE_METANEXT); - - return k; -} - -#if defined (READLINE_CALLBACKS) -int -_rl_dispatch_callback (cxt) - _rl_keyseq_cxt *cxt; -{ - int nkey, r; - - /* For now */ - /* The first time this context is used, we want to read input and dispatch - on it. When traversing the chain of contexts back `up', we want to use - the value from the next context down. We're simulating recursion using - a chain of contexts. */ - if ((cxt->flags & KSEQ_DISPATCHED) == 0) - { - nkey = _rl_subseq_getchar (cxt->okey); - if (nkey < 0) - { - _rl_abort_internal (); - return -1; - } - r = _rl_dispatch_subseq (nkey, cxt->dmap, cxt->subseq_arg); - cxt->flags |= KSEQ_DISPATCHED; - } - else - r = cxt->childval; - - /* For now */ - if (r != -3) /* don't do this if we indicate there will be other matches */ - r = _rl_subseq_result (r, cxt->oldmap, cxt->okey, (cxt->flags & KSEQ_SUBSEQ)); - - RL_CHECK_SIGNALS (); - /* We only treat values < 0 specially to simulate recursion. */ - if (r >= 0 || (r == -1 && (cxt->flags & KSEQ_SUBSEQ) == 0)) /* success! or failure! */ - { - _rl_keyseq_chain_dispose (); - RL_UNSETSTATE (RL_STATE_MULTIKEY); - return r; - } - - if (r != -3) /* magic value that says we added to the chain */ - _rl_kscxt = cxt->ocxt; - if (_rl_kscxt) - _rl_kscxt->childval = r; - if (r != -3) - _rl_keyseq_cxt_dispose (cxt); - - return r; -} -#endif /* READLINE_CALLBACKS */ - -/* Do the command associated with KEY in MAP. - If the associated command is really a keymap, then read - another key, and dispatch into that map. */ -int -_rl_dispatch (key, map) - register int key; - Keymap map; -{ - _rl_dispatching_keymap = map; - return _rl_dispatch_subseq (key, map, 0); -} - -int -_rl_dispatch_subseq (key, map, got_subseq) - register int key; - Keymap map; - int got_subseq; -{ - int r, newkey; - char *macro; - rl_command_func_t *func; -#if defined (READLINE_CALLBACKS) - _rl_keyseq_cxt *cxt; -#endif - - if (META_CHAR (key) && _rl_convert_meta_chars_to_ascii) - { - if (map[ESC].type == ISKMAP) - { - if (RL_ISSTATE (RL_STATE_MACRODEF)) - _rl_add_macro_char (ESC); - RESIZE_KEYSEQ_BUFFER (); - rl_executing_keyseq[rl_key_sequence_length++] = ESC; - map = FUNCTION_TO_KEYMAP (map, ESC); - key = UNMETA (key); - return (_rl_dispatch (key, map)); - } - else - rl_ding (); - return 0; - } - - if (RL_ISSTATE (RL_STATE_MACRODEF)) - _rl_add_macro_char (key); - - r = 0; - switch (map[key].type) - { - case ISFUNC: - func = map[key].function; - if (func) - { - /* Special case rl_do_lowercase_version (). */ - if (func == rl_do_lowercase_version) - /* Should we do anything special if key == ANYOTHERKEY? */ - return (_rl_dispatch (_rl_to_lower (key), map)); - - rl_executing_keymap = map; - rl_executing_key = key; - - RESIZE_KEYSEQ_BUFFER(); - rl_executing_keyseq[rl_key_sequence_length++] = key; - rl_executing_keyseq[rl_key_sequence_length] = '\0'; - - rl_dispatching = 1; - RL_SETSTATE(RL_STATE_DISPATCHING); - r = (*func) (rl_numeric_arg * rl_arg_sign, key); - RL_UNSETSTATE(RL_STATE_DISPATCHING); - rl_dispatching = 0; - - /* 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 (rl_pending_input == 0 && map[key].function != rl_digit_argument) - rl_last_func = map[key].function; - - RL_CHECK_SIGNALS (); - } - else if (map[ANYOTHERKEY].function) - { - /* OK, there's no function bound in this map, but there is a - shadow function that was overridden when the current keymap - was created. Return -2 to note that. */ - if (RL_ISSTATE (RL_STATE_MACROINPUT)) - _rl_prev_macro_key (); - else - _rl_unget_char (key); - return -2; - } - else if (got_subseq) - { - /* Return -1 to note that we're in a subsequence, but we don't - have a matching key, nor was one overridden. This means - we need to back up the recursion chain and find the last - subsequence that is bound to a function. */ - if (RL_ISSTATE (RL_STATE_MACROINPUT)) - _rl_prev_macro_key (); - else - _rl_unget_char (key); - return -1; - } - else - { -#if defined (READLINE_CALLBACKS) - RL_UNSETSTATE (RL_STATE_MULTIKEY); - _rl_keyseq_chain_dispose (); -#endif - _rl_abort_internal (); - return -1; - } - break; - - case ISKMAP: - if (map[key].function != 0) - { -#if defined (VI_MODE) - /* The only way this test will be true is if a subsequence has been - bound starting with ESC, generally the arrow keys. What we do is - check whether there's input in the queue, which there generally - will be if an arrow key has been pressed, and, if there's not, - just dispatch to (what we assume is) rl_vi_movement_mode right - away. This is essentially an input test with a zero timeout (by - default) or a timeout determined by the value of `keyseq-timeout' */ - /* _rl_keyseq_timeout specified in milliseconds; _rl_input_queued - takes microseconds, so multiply by 1000 */ - if (rl_editing_mode == vi_mode && key == ESC && map == vi_insertion_keymap - && _rl_input_queued ((_rl_keyseq_timeout > 0) ? _rl_keyseq_timeout*1000 : 0) == 0) - return (_rl_dispatch (ANYOTHERKEY, FUNCTION_TO_KEYMAP (map, key))); -#endif - - RESIZE_KEYSEQ_BUFFER (); - rl_executing_keyseq[rl_key_sequence_length++] = key; - _rl_dispatching_keymap = FUNCTION_TO_KEYMAP (map, key); - - /* Allocate new context here. Use linked contexts (linked through - cxt->ocxt) to simulate recursion */ -#if defined (READLINE_CALLBACKS) - if (RL_ISSTATE (RL_STATE_CALLBACK)) - { - /* Return 0 only the first time, to indicate success to - _rl_callback_read_char. The rest of the time, we're called - from _rl_dispatch_callback, so we return -3 to indicate - special handling is necessary. */ - r = RL_ISSTATE (RL_STATE_MULTIKEY) ? -3 : 0; - cxt = _rl_keyseq_cxt_alloc (); - - if (got_subseq) - cxt->flags |= KSEQ_SUBSEQ; - cxt->okey = key; - cxt->oldmap = map; - cxt->dmap = _rl_dispatching_keymap; - cxt->subseq_arg = got_subseq || cxt->dmap[ANYOTHERKEY].function; - - RL_SETSTATE (RL_STATE_MULTIKEY); - _rl_kscxt = cxt; - - return r; /* don't indicate immediate success */ - } -#endif - - /* Tentative inter-character timeout for potential multi-key - sequences? If no input within timeout, abort sequence and - act as if we got non-matching input. */ - /* _rl_keyseq_timeout specified in milliseconds; _rl_input_queued - takes microseconds, so multiply by 1000 */ - if (_rl_keyseq_timeout > 0 && - (RL_ISSTATE (RL_STATE_INPUTPENDING|RL_STATE_MACROINPUT) == 0) && - _rl_pushed_input_available () == 0 && - _rl_dispatching_keymap[ANYOTHERKEY].function && - _rl_input_queued (_rl_keyseq_timeout*1000) == 0) - return (_rl_subseq_result (-2, map, key, got_subseq)); - - newkey = _rl_subseq_getchar (key); - if (newkey < 0) - { - _rl_abort_internal (); - return -1; - } - - r = _rl_dispatch_subseq (newkey, _rl_dispatching_keymap, got_subseq || map[ANYOTHERKEY].function); - return _rl_subseq_result (r, map, key, got_subseq); - } - else - { - _rl_abort_internal (); - return -1; - } - break; - - case ISMACR: - if (map[key].function != 0) - { - rl_executing_keyseq[rl_key_sequence_length] = '\0'; - macro = savestring ((char *)map[key].function); - _rl_with_macro_input (macro); - return 0; - } - break; - } -#if defined (VI_MODE) - if (rl_editing_mode == vi_mode && _rl_keymap == vi_movement_keymap && - key != ANYOTHERKEY && - rl_key_sequence_length == 1 && /* XXX */ - _rl_vi_textmod_command (key)) - _rl_vi_set_last (key, rl_numeric_arg, rl_arg_sign); -#endif - - return (r); -} - -static int -_rl_subseq_result (r, map, key, got_subseq) - int r; - Keymap map; - int key, got_subseq; -{ - Keymap m; - int type, nt; - rl_command_func_t *func, *nf; - - if (r == -2) - /* We didn't match anything, and the keymap we're indexed into - shadowed a function previously bound to that prefix. Call - the function. The recursive call to _rl_dispatch_subseq has - already taken care of pushing any necessary input back onto - the input queue with _rl_unget_char. */ - { - m = _rl_dispatching_keymap; - type = m[ANYOTHERKEY].type; - func = m[ANYOTHERKEY].function; - if (type == ISFUNC && func == rl_do_lowercase_version) - r = _rl_dispatch (_rl_to_lower (key), map); - else if (type == ISFUNC && func == rl_insert) - { - /* If the function that was shadowed was self-insert, we - somehow need a keymap with map[key].func == self-insert. - Let's use this one. */ - nt = m[key].type; - nf = m[key].function; - - m[key].type = type; - m[key].function = func; - r = _rl_dispatch (key, m); - m[key].type = nt; - m[key].function = nf; - } - else - r = _rl_dispatch (ANYOTHERKEY, m); - } - else if (r && map[ANYOTHERKEY].function) - { - /* We didn't match (r is probably -1), so return something to - tell the caller that it should try ANYOTHERKEY for an - overridden function. */ - if (RL_ISSTATE (RL_STATE_MACROINPUT)) - _rl_prev_macro_key (); - else - _rl_unget_char (key); - _rl_dispatching_keymap = map; - return -2; - } - else if (r && got_subseq) - { - /* OK, back up the chain. */ - if (RL_ISSTATE (RL_STATE_MACROINPUT)) - _rl_prev_macro_key (); - else - _rl_unget_char (key); - _rl_dispatching_keymap = map; - return -1; - } - - return r; -} - -/* **************************************************************** */ -/* */ -/* Initializations */ -/* */ -/* **************************************************************** */ - -/* Initialize readline (and terminal if not already). */ -int -rl_initialize () -{ - /* If we have never been called before, initialize the - terminal and data structures. */ - if (!rl_initialized) - { - RL_SETSTATE(RL_STATE_INITIALIZING); - readline_initialize_everything (); - RL_UNSETSTATE(RL_STATE_INITIALIZING); - rl_initialized++; - RL_SETSTATE(RL_STATE_INITIALIZED); - } - - /* Initialize the current line information. */ - _rl_init_line_state (); - - /* We aren't done yet. We haven't even gotten started yet! */ - rl_done = 0; - RL_UNSETSTATE(RL_STATE_DONE); - - /* Tell the history routines what is going on. */ - _rl_start_using_history (); - - /* Make the display buffer match the state of the line. */ - rl_reset_line_state (); - - /* No such function typed yet. */ - rl_last_func = (rl_command_func_t *)NULL; - - /* Parsing of key-bindings begins in an enabled state. */ - _rl_parsing_conditionalized_out = 0; - -#if defined (VI_MODE) - if (rl_editing_mode == vi_mode) - _rl_vi_initialize_line (); -#endif - - /* Each line starts in insert mode (the default). */ - _rl_set_insert_mode (RL_IM_DEFAULT, 1); - - return 0; -} - -#if 0 -#if defined (__EMX__) -static void -_emx_build_environ () -{ - TIB *tibp; - PIB *pibp; - char *t, **tp; - int c; - - DosGetInfoBlocks (&tibp, &pibp); - t = pibp->pib_pchenv; - for (c = 1; *t; c++) - t += strlen (t) + 1; - tp = environ = (char **)xmalloc ((c + 1) * sizeof (char *)); - t = pibp->pib_pchenv; - while (*t) - { - *tp++ = t; - t += strlen (t) + 1; - } - *tp = 0; -} -#endif /* __EMX__ */ -#endif - -/* Initialize the entire state of the world. */ -static void -readline_initialize_everything () -{ -#if 0 -#if defined (__EMX__) - if (environ == 0) - _emx_build_environ (); -#endif -#endif - -#if 0 - /* Find out if we are running in Emacs -- UNUSED. */ - running_in_emacs = sh_get_env_value ("EMACS") != (char *)0; -#endif - - /* Set up input and output if they are not already set up. */ - if (!rl_instream) - rl_instream = stdin; - - if (!rl_outstream) - rl_outstream = stdout; - - /* Bind _rl_in_stream and _rl_out_stream immediately. These values - may change, but they may also be used before readline_internal () - is called. */ - _rl_in_stream = rl_instream; - _rl_out_stream = rl_outstream; - - /* Allocate data structures. */ - if (rl_line_buffer == 0) - rl_line_buffer = (char *)xmalloc (rl_line_buffer_len = DEFAULT_BUFFER_SIZE); - - /* Initialize the terminal interface. */ - if (rl_terminal_name == 0) - rl_terminal_name = sh_get_env_value ("TERM"); - _rl_init_terminal_io (rl_terminal_name); - - /* Bind tty characters to readline functions. */ - readline_default_bindings (); - - /* Initialize the function names. */ - rl_initialize_funmap (); - - /* Decide whether we should automatically go into eight-bit mode. */ - _rl_init_eightbit (); - - /* Read in the init file. */ - rl_read_init_file ((char *)NULL); - - /* XXX */ - if (_rl_horizontal_scroll_mode && _rl_term_autowrap) - { - _rl_screenwidth--; - _rl_screenchars -= _rl_screenheight; - } - - /* Override the effect of any `set keymap' assignments in the - inputrc file. */ - rl_set_keymap_from_edit_mode (); - - /* Try to bind a common arrow key prefix, if not already bound. */ - bind_arrow_keys (); - - /* If the completion parser's default word break characters haven't - been set yet, then do so now. */ - if (rl_completer_word_break_characters == (char *)NULL) - rl_completer_word_break_characters = (char *)rl_basic_word_break_characters; - -#if defined (COLOR_SUPPORT) - if (_rl_colored_stats) - _rl_parse_colors (); -#endif - - rl_executing_keyseq = malloc (_rl_executing_keyseq_size = 16); - if (rl_executing_keyseq) - rl_executing_keyseq[0] = '\0'; -} - -/* If this system allows us to look at the values of the regular - input editing characters, then bind them to their readline - equivalents, iff the characters are not bound to keymaps. */ -static void -readline_default_bindings () -{ - if (_rl_bind_stty_chars) - rl_tty_set_default_bindings (_rl_keymap); -} - -/* Reset the default bindings for the terminal special characters we're - interested in back to rl_insert and read the new ones. */ -static void -reset_default_bindings () -{ - if (_rl_bind_stty_chars) - { - rl_tty_unset_default_bindings (_rl_keymap); - rl_tty_set_default_bindings (_rl_keymap); - } -} - -/* Bind some common arrow key sequences in MAP. */ -static void -bind_arrow_keys_internal (map) - Keymap map; -{ - Keymap xkeymap; - - xkeymap = _rl_keymap; - _rl_keymap = map; - -#if defined (__MSDOS__) - rl_bind_keyseq_if_unbound ("\033[0A", rl_get_previous_history); - rl_bind_keyseq_if_unbound ("\033[0B", rl_backward_char); - rl_bind_keyseq_if_unbound ("\033[0C", rl_forward_char); - rl_bind_keyseq_if_unbound ("\033[0D", rl_get_next_history); -#endif - - rl_bind_keyseq_if_unbound ("\033[A", rl_get_previous_history); - rl_bind_keyseq_if_unbound ("\033[B", rl_get_next_history); - rl_bind_keyseq_if_unbound ("\033[C", rl_forward_char); - rl_bind_keyseq_if_unbound ("\033[D", rl_backward_char); - rl_bind_keyseq_if_unbound ("\033[H", rl_beg_of_line); - rl_bind_keyseq_if_unbound ("\033[F", rl_end_of_line); - - rl_bind_keyseq_if_unbound ("\033OA", rl_get_previous_history); - rl_bind_keyseq_if_unbound ("\033OB", rl_get_next_history); - rl_bind_keyseq_if_unbound ("\033OC", rl_forward_char); - rl_bind_keyseq_if_unbound ("\033OD", rl_backward_char); - rl_bind_keyseq_if_unbound ("\033OH", rl_beg_of_line); - rl_bind_keyseq_if_unbound ("\033OF", rl_end_of_line); - -#if defined (__MINGW32__) - rl_bind_keyseq_if_unbound ("\340H", rl_get_previous_history); - rl_bind_keyseq_if_unbound ("\340P", rl_get_next_history); - rl_bind_keyseq_if_unbound ("\340M", rl_forward_char); - rl_bind_keyseq_if_unbound ("\340K", rl_backward_char); - rl_bind_keyseq_if_unbound ("\340G", rl_beg_of_line); - rl_bind_keyseq_if_unbound ("\340O", rl_end_of_line); - rl_bind_keyseq_if_unbound ("\340S", rl_delete); - rl_bind_keyseq_if_unbound ("\340R", rl_overwrite_mode); - - /* These may or may not work because of the embedded NUL. */ - rl_bind_keyseq_if_unbound ("\\000H", rl_get_previous_history); - rl_bind_keyseq_if_unbound ("\\000P", rl_get_next_history); - rl_bind_keyseq_if_unbound ("\\000M", rl_forward_char); - rl_bind_keyseq_if_unbound ("\\000K", rl_backward_char); - rl_bind_keyseq_if_unbound ("\\000G", rl_beg_of_line); - rl_bind_keyseq_if_unbound ("\\000O", rl_end_of_line); - rl_bind_keyseq_if_unbound ("\\000S", rl_delete); - rl_bind_keyseq_if_unbound ("\\000R", rl_overwrite_mode); -#endif - - _rl_keymap = xkeymap; -} - -/* Try and bind the common arrow key prefixes after giving termcap and - the inputrc file a chance to bind them and create `real' keymaps - for the arrow key prefix. */ -static void -bind_arrow_keys () -{ - bind_arrow_keys_internal (emacs_standard_keymap); - -#if defined (VI_MODE) - bind_arrow_keys_internal (vi_movement_keymap); - /* Unbind vi_movement_keymap[ESC] to allow users to repeatedly hit ESC - in vi command mode while still allowing the arrow keys to work. */ - if (vi_movement_keymap[ESC].type == ISKMAP) - rl_bind_keyseq_in_map ("\033", (rl_command_func_t *)NULL, vi_movement_keymap); - bind_arrow_keys_internal (vi_insertion_keymap); -#endif -} - -/* **************************************************************** */ -/* */ -/* Saving and Restoring Readline's state */ -/* */ -/* **************************************************************** */ - -int -rl_save_state (sp) - struct readline_state *sp; -{ - if (sp == 0) - return -1; - - sp->point = rl_point; - sp->end = rl_end; - sp->mark = rl_mark; - sp->buffer = rl_line_buffer; - sp->buflen = rl_line_buffer_len; - sp->ul = rl_undo_list; - sp->prompt = rl_prompt; - - sp->rlstate = rl_readline_state; - sp->done = rl_done; - sp->kmap = _rl_keymap; - - sp->lastfunc = rl_last_func; - sp->insmode = rl_insert_mode; - sp->edmode = rl_editing_mode; - sp->kseqlen = rl_key_sequence_length; - sp->inf = rl_instream; - sp->outf = rl_outstream; - sp->pendingin = rl_pending_input; - sp->macro = rl_executing_macro; - - sp->catchsigs = rl_catch_signals; - sp->catchsigwinch = rl_catch_sigwinch; - - return (0); -} - -int -rl_restore_state (sp) - struct readline_state *sp; -{ - if (sp == 0) - return -1; - - rl_point = sp->point; - rl_end = sp->end; - rl_mark = sp->mark; - the_line = rl_line_buffer = sp->buffer; - rl_line_buffer_len = sp->buflen; - rl_undo_list = sp->ul; - rl_prompt = sp->prompt; - - rl_readline_state = sp->rlstate; - rl_done = sp->done; - _rl_keymap = sp->kmap; - - rl_last_func = sp->lastfunc; - rl_insert_mode = sp->insmode; - rl_editing_mode = sp->edmode; - rl_key_sequence_length = sp->kseqlen; - rl_instream = sp->inf; - rl_outstream = sp->outf; - rl_pending_input = sp->pendingin; - rl_executing_macro = sp->macro; - - rl_catch_signals = sp->catchsigs; - rl_catch_sigwinch = sp->catchsigwinch; - - return (0); -} diff --git a/lib/readline/readline.h b/lib/readline/readline.h index 924bbfb0..2081b197 100644 --- a/lib/readline/readline.h +++ b/lib/readline/readline.h @@ -98,6 +98,9 @@ extern int rl_clear_screen PARAMS((int, int)); extern int rl_skip_csi_sequence PARAMS((int, int)); extern int rl_arrow_keys PARAMS((int, int)); +extern int rl_previous_screen_line PARAMS((int, int)); +extern int rl_next_screen_line PARAMS((int, int)); + /* Bindable commands for inserting and deleting text. */ extern int rl_insert PARAMS((int, int)); extern int rl_quoted_insert PARAMS((int, int)); @@ -329,6 +332,7 @@ extern char *rl_untranslate_keyseq PARAMS((int)); extern rl_command_func_t *rl_named_function PARAMS((const char *)); extern rl_command_func_t *rl_function_of_keyseq PARAMS((const char *, Keymap, int *)); +extern rl_command_func_t *rl_function_of_keyseq_len PARAMS((const char *, size_t, Keymap, int *)); extern void rl_list_funmap_names PARAMS((void)); extern char **rl_invoking_keyseqs_in_map PARAMS((rl_command_func_t *, Keymap)); @@ -343,6 +347,7 @@ extern int rl_parse_and_bind PARAMS((char *)); /* Functions for manipulating keymaps. */ extern Keymap rl_make_bare_keymap PARAMS((void)); +extern int rl_empty_keymap PARAMS((Keymap)); extern Keymap rl_copy_keymap PARAMS((Keymap)); extern Keymap rl_make_keymap PARAMS((void)); extern void rl_discard_keymap PARAMS((Keymap)); @@ -413,6 +418,7 @@ extern void rl_deprep_terminal PARAMS((void)); extern void rl_tty_set_default_bindings PARAMS((Keymap)); extern void rl_tty_unset_default_bindings PARAMS((Keymap)); +extern int rl_tty_set_echoing PARAMS((int)); extern int rl_reset_terminal PARAMS((const char *)); extern void rl_resize_terminal PARAMS((void)); extern void rl_set_screen_size PARAMS((int, int)); @@ -443,6 +449,7 @@ extern void rl_reset_after_signal PARAMS((void)); extern void rl_free_line_state PARAMS((void)); extern int rl_pending_signal PARAMS((void)); +extern void rl_check_signals PARAMS((void)); extern void rl_echo_signal_char PARAMS((int)); diff --git a/lib/readline/rlconf.h b/lib/readline/rlconf.h index 98c970aa..b6d6a2f1 100644 --- a/lib/readline/rlconf.h +++ b/lib/readline/rlconf.h @@ -42,7 +42,7 @@ /* The next-to-last-ditch effort file name for a user-specific init file. */ #define DEFAULT_INPUTRC "~/.inputrc" -/* The ultimate last-ditch filenname for an init file -- system-wide. */ +/* The ultimate last-ditch filename for an init file -- system-wide. */ #define SYS_INPUTRC "/etc/inputrc" /* If defined, expand tabs to spaces. */ diff --git a/lib/readline/rlmbutil.h b/lib/readline/rlmbutil.h index 4748a610..8b88de40 100644 --- a/lib/readline/rlmbutil.h +++ b/lib/readline/rlmbutil.h @@ -172,6 +172,8 @@ _rl_wcwidth (wc) # define IS_COMBINING_CHAR(x) (WCWIDTH(x) == 0) #endif +#define UTF8_SINGLEBYTE(c) (((c) & 0x80) == 0) + #else /* !HANDLE_MULTIBYTE */ #undef MB_LEN_MAX @@ -196,6 +198,12 @@ _rl_wcwidth (wc) #define MB_INVALIDCH(x) (0) #define MB_NULLWCH(x) (0) +#define UTF8_SINGLEBYTE(c) (1) + +#if !defined (HAVE_WCHAR_T) && !defined (wchar_t) +# define wchar_t int +#endif + #endif /* !HANDLE_MULTIBYTE */ extern int rl_byte_oriented; diff --git a/lib/readline/rlprivate.h b/lib/readline/rlprivate.h index fc3856a1..05ee9302 100644 --- a/lib/readline/rlprivate.h +++ b/lib/readline/rlprivate.h @@ -26,6 +26,7 @@ #include "rlconf.h" /* for VISIBLE_STATS */ #include "rlstdc.h" #include "posixjmp.h" /* defines procenv_t */ +#include "rlmbutil.h" /* for HANDLE_MULTIBYTE */ /************************************************************************* * * @@ -64,6 +65,7 @@ #define SF_FOUND 0x02 #define SF_FAILED 0x04 #define SF_CHGKMAP 0x08 +#define SF_PATTERN 0x10 /* unused so far */ typedef struct __rl_search_context { @@ -305,10 +307,11 @@ extern int _rl_search_getchar PARAMS((_rl_search_cxt *)); #define BRACK_PASTE_SLEN 6 #define BRACK_PASTE_INIT "\033[?2004h" -#define BRACK_PASTE_FINI "\033[?2004l" +#define BRACK_PASTE_FINI "\033[?2004l\r" /* macro.c */ extern void _rl_with_macro_input PARAMS((char *)); +extern int _rl_peek_macro_key PARAMS((void)); extern int _rl_next_macro_key PARAMS((void)); extern int _rl_prev_macro_key PARAMS((void)); extern void _rl_push_executing_macro PARAMS((void)); @@ -330,6 +333,7 @@ extern void _rl_set_insert_mode PARAMS((int, int)); extern void _rl_revert_all_lines PARAMS((void)); /* nls.c */ +extern char *_rl_init_locale PARAMS((void)); extern int _rl_init_eightbit PARAMS((void)); /* parens.c */ @@ -534,6 +538,7 @@ extern int _rl_enable_keypad; extern int _rl_enable_meta; extern char *_rl_term_clreol; extern char *_rl_term_clrpag; +extern char *_rl_term_clrscroll; extern char *_rl_term_im; extern char *_rl_term_ic; extern char *_rl_term_ei; diff --git a/lib/readline/rltty.c b/lib/readline/rltty.c index b1c79294..6d907192 100644 --- a/lib/readline/rltty.c +++ b/lib/readline/rltty.c @@ -1,7 +1,7 @@ /* rltty.c -- functions to prepare and restore the terminal for readline's use. */ -/* Copyright (C) 1992-2016 Free Software Foundation, Inc. +/* Copyright (C) 1992-2017 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. @@ -130,8 +130,7 @@ static void prepare_terminal_settings PARAMS((int, TIOTYPE, TIOTYPE *)); static void set_special_char PARAMS((Keymap, TIOTYPE *, int, rl_command_func_t *)); static void -save_tty_chars (tiop) - TIOTYPE *tiop; +save_tty_chars (TIOTYPE *tiop) { _rl_last_tty_chars = _rl_tty_chars; @@ -168,9 +167,7 @@ save_tty_chars (tiop) } static int -get_tty_settings (tty, tiop) - int tty; - TIOTYPE *tiop; +get_tty_settings (int tty, TIOTYPE *tiop) { set_winsize (tty); @@ -200,9 +197,7 @@ get_tty_settings (tty, tiop) } static int -set_tty_settings (tty, tiop) - int tty; - TIOTYPE *tiop; +set_tty_settings (int tty, TIOTYPE *tiop) { if (tiop->flags & SGTTY_SET) { @@ -239,9 +234,7 @@ set_tty_settings (tty, tiop) } static void -prepare_terminal_settings (meta_flag, oldtio, tiop) - int meta_flag; - TIOTYPE oldtio, *tiop; +prepare_terminal_settings (int meta_flag, TIOTYPE oldtio, TIOTYPE *tiop) { _rl_echoing_p = (oldtio.sgttyb.sg_flags & ECHO); _rl_echoctl = (oldtio.sgttyb.sg_flags & ECHOCTL); @@ -357,8 +350,7 @@ static void _rl_bind_tty_special_chars PARAMS((Keymap, TIOTYPE)); #endif static void -save_tty_chars (tiop) - TIOTYPE *tiop; +save_tty_chars (TIOTYPE *tiop) { _rl_last_tty_chars = _rl_tty_chars; @@ -403,7 +395,7 @@ save_tty_chars (tiop) #if defined (_AIX) || defined (_AIX41) /* Currently this is only used on AIX */ static void -rltty_warning (msg) +rltty_warning (char *msg) char *msg; { _rl_errmsg ("warning: %s", msg); @@ -412,8 +404,7 @@ rltty_warning (msg) #if defined (_AIX) void -setopost(tp) -TIOTYPE *tp; +setopost (TIOTYPE *tp) { if ((tp->c_oflag & OPOST) == 0) { @@ -424,9 +415,7 @@ TIOTYPE *tp; #endif static int -_get_tty_settings (tty, tiop) - int tty; - TIOTYPE *tiop; +_get_tty_settings (int tty, TIOTYPE *tiop) { int ioctl_ret; @@ -457,9 +446,7 @@ _get_tty_settings (tty, tiop) } static int -get_tty_settings (tty, tiop) - int tty; - TIOTYPE *tiop; +get_tty_settings (int tty, TIOTYPE *tiop) { set_winsize (tty); @@ -475,9 +462,7 @@ get_tty_settings (tty, tiop) } static int -_set_tty_settings (tty, tiop) - int tty; - TIOTYPE *tiop; +_set_tty_settings (int tty, TIOTYPE *tiop) { while (SETATTR (tty, tiop) < 0) { @@ -489,9 +474,7 @@ _set_tty_settings (tty, tiop) } static int -set_tty_settings (tty, tiop) - int tty; - TIOTYPE *tiop; +set_tty_settings (int tty, TIOTYPE *tiop) { if (_set_tty_settings (tty, tiop) < 0) return -1; @@ -518,10 +501,11 @@ set_tty_settings (tty, tiop) } static void -prepare_terminal_settings (meta_flag, oldtio, tiop) - int meta_flag; - TIOTYPE oldtio, *tiop; +prepare_terminal_settings (int meta_flag, TIOTYPE oldtio, TIOTYPE *tiop) { + int sc; + Keymap kmap; + _rl_echoing_p = (oldtio.c_lflag & ECHO); #if defined (ECHOCTL) _rl_echoctl = (oldtio.c_lflag & ECHOCTL); @@ -578,6 +562,20 @@ prepare_terminal_settings (meta_flag, oldtio, tiop) tiop->c_cc[VDSUSP] = _POSIX_VDISABLE; #endif + /* Conditionally disable some other tty special characters if there is a + key binding for them in the current keymap. Readline ordinarily doesn't + bind these characters, but an application or user might. */ +#if defined (VI_MODE) + kmap = (rl_editing_mode == vi_mode) ? vi_insertion_keymap : _rl_keymap; +#else + kmap = _rl_keymap; +#endif +#if defined (VDISCARD) + sc = tiop->c_cc[VDISCARD]; + if (sc != _POSIX_VDISABLE && kmap[(unsigned char)sc].type == ISFUNC) + tiop->c_cc[VDISCARD] = _POSIX_VDISABLE; +#endif /* VDISCARD */ + #endif /* TERMIOS_TTY_DRIVER && _POSIX_VDISABLE */ } #endif /* !NEW_TTY_DRIVER */ @@ -585,21 +583,19 @@ prepare_terminal_settings (meta_flag, oldtio, tiop) /* Put the terminal in CBREAK mode so that we can detect key presses. */ #if defined (NO_TTY_DRIVER) void -rl_prep_terminal (meta_flag) - int meta_flag; +rl_prep_terminal (int meta_flag) { _rl_echoing_p = 1; } void -rl_deprep_terminal () +rl_deprep_terminal (void) { } #else /* ! NO_TTY_DRIVER */ void -rl_prep_terminal (meta_flag) - int meta_flag; +rl_prep_terminal (int meta_flag) { int tty, nprep; TIOTYPE tio; @@ -682,7 +678,7 @@ rl_prep_terminal (meta_flag) /* Restore the terminal's normal settings and modes. */ void -rl_deprep_terminal () +rl_deprep_terminal (void) { int tty; @@ -718,8 +714,7 @@ rl_deprep_terminal () /* Set readline's idea of whether or not it is echoing output to the terminal, returning the old value. */ int -rl_tty_set_echoing (u) - int u; +rl_tty_set_echoing (int u) { int o; @@ -735,8 +730,7 @@ rl_tty_set_echoing (u) /* **************************************************************** */ int -rl_restart_output (count, key) - int count, key; +rl_restart_output (int count, int key) { #if defined (__MINGW32__) return 0; @@ -773,8 +767,7 @@ rl_restart_output (count, key) } int -rl_stop_output (count, key) - int count, key; +rl_stop_output (int count, int key) { #if defined (__MINGW32__) return 0; @@ -822,11 +815,7 @@ rl_stop_output (count, key) #elif defined (NEW_TTY_DRIVER) static void -set_special_char (kmap, tiop, sc, func) - Keymap kmap; - TIOTYPE *tiop; - int sc; - rl_command_func_t *func; +set_special_char (Keymap kmap, TIOTYPE *tiop, int sc, rl_command_func_t *func) { if (sc != -1 && kmap[(unsigned char)sc].type == ISFUNC) kmap[(unsigned char)sc].function = func; @@ -837,9 +826,7 @@ set_special_char (kmap, tiop, sc, func) kmap[(unsigned char)c].function = rl_insert; static void -_rl_bind_tty_special_chars (kmap, ttybuff) - Keymap kmap; - TIOTYPE ttybuff; +_rl_bind_tty_special_chars (Keymap kmap, TIOTYPE ttybuff) { if (ttybuff.flags & SGTTY_SET) { @@ -858,11 +845,7 @@ _rl_bind_tty_special_chars (kmap, ttybuff) #else /* !NEW_TTY_DRIVER */ static void -set_special_char (kmap, tiop, sc, func) - Keymap kmap; - TIOTYPE *tiop; - int sc; - rl_command_func_t *func; +set_special_char (Keymap kmap, TIOTYPE *tiop, int sc, rl_command_func_t *func) { unsigned char uc; @@ -877,9 +860,7 @@ set_special_char (kmap, tiop, sc, func) kmap[uc].function = rl_insert; static void -_rl_bind_tty_special_chars (kmap, ttybuff) - Keymap kmap; - TIOTYPE ttybuff; +_rl_bind_tty_special_chars (Keymap kmap, TIOTYPE ttybuff) { SET_SPECIAL (VERASE, rl_rubout); SET_SPECIAL (VKILL, rl_unix_line_discard); @@ -903,8 +884,7 @@ _rl_bind_tty_special_chars (kmap, ttybuff) /* Set the system's default editing characters to their readline equivalents in KMAP. Should be static, now that we have rl_tty_set_default_bindings. */ void -rltty_set_default_bindings (kmap) - Keymap kmap; +rltty_set_default_bindings (Keymap kmap) { #if !defined (NO_TTY_DRIVER) TIOTYPE ttybuff; @@ -920,8 +900,7 @@ rltty_set_default_bindings (kmap) /* New public way to set the system default editing chars to their readline equivalents. */ void -rl_tty_set_default_bindings (kmap) - Keymap kmap; +rl_tty_set_default_bindings (Keymap kmap) { rltty_set_default_bindings (kmap); } @@ -931,8 +910,7 @@ rl_tty_set_default_bindings (kmap) chars with save_tty_chars(). This only works on POSIX termios or termio systems. */ void -rl_tty_unset_default_bindings (kmap) - Keymap kmap; +rl_tty_unset_default_bindings (Keymap kmap) { /* Don't bother before we've saved the tty special chars at least once. */ if (RL_ISSTATE(RL_STATE_TTYCSAVED) == 0) @@ -954,13 +932,13 @@ rl_tty_unset_default_bindings (kmap) #if defined (NEW_TTY_DRIVER) || defined (NO_TTY_DRIVER) int -_rl_disable_tty_signals () +_rl_disable_tty_signals (void) { return 0; } int -_rl_restore_tty_signals () +_rl_restore_tty_signals (void) { return 0; } @@ -970,7 +948,7 @@ static TIOTYPE sigstty, nosigstty; static int tty_sigs_disabled = 0; int -_rl_disable_tty_signals () +_rl_disable_tty_signals (void) { if (tty_sigs_disabled) return 0; @@ -991,7 +969,7 @@ _rl_disable_tty_signals () } int -_rl_restore_tty_signals () +_rl_restore_tty_signals (void) { int r; diff --git a/lib/readline/savestring.c b/lib/readline/savestring.c index af985380..f4bb6aa1 100644 --- a/lib/readline/savestring.c +++ b/lib/readline/savestring.c @@ -1,6 +1,6 @@ /* savestring.c - function version of savestring for backwards compatibility */ -/* Copyright (C) 1998,2003 Free Software Foundation, Inc. +/* Copyright (C) 1998,2003,2017 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. @@ -30,8 +30,7 @@ /* Backwards compatibility, now that savestring has been removed from all `public' readline header files. */ char * -savestring (s) - const char *s; +savestring (const char *s) { char *ret; diff --git a/lib/readline/search.c b/lib/readline/search.c index 45d95d2e..64925611 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-2015 Free Software Foundation, Inc. +/* Copyright (C) 1992-2017 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,8 +73,8 @@ static char *history_search_string; static int history_string_size; static void make_history_line_current PARAMS((HIST_ENTRY *)); -static int noninc_search_from_pos PARAMS((char *, int, int)); -static int noninc_dosearch PARAMS((char *, int)); +static int noninc_search_from_pos PARAMS((char *, int, int, int, int *)); +static int noninc_dosearch PARAMS((char *, int, int)); static int noninc_search PARAMS((int, int)); static int rl_history_search_internal PARAMS((int, int)); static void rl_history_search_reinit PARAMS((int)); @@ -87,8 +87,7 @@ static int _rl_nsearch_dispatch PARAMS((_rl_search_cxt *, int)); current line. This doesn't do anything with rl_point; the caller must set it. */ static void -make_history_line_current (entry) - HIST_ENTRY *entry; +make_history_line_current (HIST_ENTRY *entry) { _rl_replace_text (entry->line, 0, rl_end); _rl_fix_point (1); @@ -112,11 +111,10 @@ make_history_line_current (entry) for STRING. DIR < 0 means to search backwards through the history list, DIR >= 0 means to search forward. */ static int -noninc_search_from_pos (string, pos, dir) - char *string; - int pos, dir; +noninc_search_from_pos (char *string, int pos, int dir, int flags, int *ncp) { - int ret, old; + int ret, old, sflags; + char *s; if (pos < 0) return -1; @@ -126,12 +124,28 @@ noninc_search_from_pos (string, pos, dir) return -1; RL_SETSTATE(RL_STATE_SEARCH); - if (*string == '^') + /* These functions return the match offset in the line; history_offset gives + the matching line in the history list */ + if (flags & SF_PATTERN) + { + s = string; + sflags = 0; /* Non-anchored search */ + if (*s == '^') + { + sflags |= ANCHORED_SEARCH; + s++; + } + ret = _hs_history_patsearch (string, dir, sflags); + } + else if (*string == '^') ret = history_search_prefix (string + 1, dir); else ret = history_search (string, dir); RL_UNSETSTATE(RL_STATE_SEARCH); + if (ncp) + *ncp = ret; /* caller will catch -1 to indicate no-op */ + if (ret != -1) ret = where_history (); @@ -143,9 +157,7 @@ noninc_search_from_pos (string, pos, dir) search is backwards through previous entries, else through subsequent entries. Returns 1 if the search was successful, 0 otherwise. */ static int -noninc_dosearch (string, dir) - char *string; - int dir; +noninc_dosearch (char *string, int dir, int flags) { int oldpos, pos; HIST_ENTRY *entry; @@ -156,7 +168,7 @@ noninc_dosearch (string, dir) return 0; } - pos = noninc_search_from_pos (string, noninc_history_pos + dir, dir); + pos = noninc_search_from_pos (string, noninc_history_pos + dir, dir, flags, (int *)0); if (pos == -1) { /* Search failed, current history position unchanged. */ @@ -188,8 +200,7 @@ noninc_dosearch (string, dir) } static _rl_search_cxt * -_rl_nsearch_init (dir, pchar) - int dir, pchar; +_rl_nsearch_init (int dir, int pchar) { _rl_search_cxt *cxt; char *p; @@ -197,6 +208,10 @@ _rl_nsearch_init (dir, pchar) cxt = _rl_scxt_alloc (RL_SEARCH_NSEARCH, 0); if (dir < 0) cxt->sflags |= SF_REVERSE; /* not strictly needed */ +#if defined (VI_MODE) + if (VI_COMMAND_MODE() && (pchar == '?' || pchar == '/')) + cxt->sflags |= SF_PATTERN; +#endif cxt->direction = dir; cxt->history_pos = cxt->save_line; @@ -224,9 +239,7 @@ _rl_nsearch_init (dir, pchar) } int -_rl_nsearch_cleanup (cxt, r) - _rl_search_cxt *cxt; - int r; +_rl_nsearch_cleanup (_rl_search_cxt *cxt, int r) { _rl_scxt_dispose (cxt, 0); _rl_nscxt = 0; @@ -237,8 +250,7 @@ _rl_nsearch_cleanup (cxt, r) } static void -_rl_nsearch_abort (cxt) - _rl_search_cxt *cxt; +_rl_nsearch_abort (_rl_search_cxt *cxt) { rl_maybe_unsave_line (); rl_clear_message (); @@ -253,10 +265,11 @@ _rl_nsearch_abort (cxt) if the caller should abort the search, 0 if we should break out of the loop, and 1 if we should continue to read characters. */ static int -_rl_nsearch_dispatch (cxt, c) - _rl_search_cxt *cxt; - int c; +_rl_nsearch_dispatch (_rl_search_cxt *cxt, int c) { + if (c < 0) + c = CTRL ('C'); + switch (c) { case CTRL('W'): @@ -306,8 +319,7 @@ _rl_nsearch_dispatch (cxt, c) using _rl_nsearch_cleanup (). Returns 1 if the search was successful, 0 otherwise. */ static int -_rl_nsearch_dosearch (cxt) - _rl_search_cxt *cxt; +_rl_nsearch_dosearch (_rl_search_cxt *cxt) { rl_mark = cxt->save_mark; @@ -340,7 +352,7 @@ _rl_nsearch_dosearch (cxt) } rl_restore_prompt (); - return (noninc_dosearch (noninc_search_string, cxt->direction)); + return (noninc_dosearch (noninc_search_string, cxt->direction, cxt->sflags&SF_PATTERN)); } /* Search non-interactively through the history list. DIR < 0 means to @@ -349,9 +361,7 @@ _rl_nsearch_dosearch (cxt) history list. PCHAR is the character to use for prompting when reading the search string; if not specified (0), it defaults to `:'. */ static int -noninc_search (dir, pchar) - int dir; - int pchar; +noninc_search (int dir, int pchar) { _rl_search_cxt *cxt; int c, r; @@ -367,6 +377,12 @@ noninc_search (dir, pchar) { c = _rl_search_getchar (cxt); + if (c < 0) + { + _rl_nsearch_abort (cxt); + return 1; + } + if (c == 0) break; @@ -384,8 +400,7 @@ noninc_search (dir, pchar) /* Search forward through the history list for a string. If the vi-mode code calls this, KEY will be `?'. */ int -rl_noninc_forward_search (count, key) - int count, key; +rl_noninc_forward_search (int count, int key) { return noninc_search (1, (key == '?') ? '?' : 0); } @@ -393,17 +408,16 @@ rl_noninc_forward_search (count, key) /* Reverse search the history list for a string. If the vi-mode code calls this, KEY will be `/'. */ int -rl_noninc_reverse_search (count, key) - int count, key; +rl_noninc_reverse_search (int count, int key) { return noninc_search (-1, (key == '/') ? '/' : 0); } /* Search forward through the history list for the last string searched - for. If there is no saved search string, abort. */ + for. If there is no saved search string, abort. If the vi-mode code + calls this, KEY will be `N'. */ int -rl_noninc_forward_search_again (count, key) - int count, key; +rl_noninc_forward_search_again (int count, int key) { int r; @@ -412,15 +426,20 @@ rl_noninc_forward_search_again (count, key) rl_ding (); return (1); } - r = noninc_dosearch (noninc_search_string, 1); +#if defined (VI_MODE) + if (VI_COMMAND_MODE() && key == 'N') + r = noninc_dosearch (noninc_search_string, 1, SF_PATTERN); + else +#endif + r = noninc_dosearch (noninc_search_string, 1, 0); return (r != 1); } /* Reverse search in the history list for the last string searched - for. If there is no saved search string, abort. */ + for. If there is no saved search string, abort. If the vi-mode code + calls this, KEY will be `n'. */ int -rl_noninc_reverse_search_again (count, key) - int count, key; +rl_noninc_reverse_search_again (int count, int key) { int r; @@ -429,18 +448,28 @@ rl_noninc_reverse_search_again (count, key) rl_ding (); return (1); } - r = noninc_dosearch (noninc_search_string, -1); +#if defined (VI_MODE) + if (VI_COMMAND_MODE() && key == 'n') + r = noninc_dosearch (noninc_search_string, -1, SF_PATTERN); + else +#endif + r = noninc_dosearch (noninc_search_string, -1, 0); return (r != 1); } #if defined (READLINE_CALLBACKS) int -_rl_nsearch_callback (cxt) - _rl_search_cxt *cxt; +_rl_nsearch_callback (_rl_search_cxt *cxt) { int c, r; c = _rl_search_getchar (cxt); + if (c <= 0) + { + if (c < 0) + _rl_nsearch_abort (cxt); + return 1; + } r = _rl_nsearch_dispatch (cxt, c); if (r != 0) return 1; @@ -451,11 +480,10 @@ _rl_nsearch_callback (cxt) #endif static int -rl_history_search_internal (count, dir) - int count, dir; +rl_history_search_internal (int count, int dir) { HIST_ENTRY *temp; - int ret, oldpos; + int ret, oldpos, newcol; char *t; rl_maybe_save_line (); @@ -469,7 +497,7 @@ rl_history_search_internal (count, dir) while (count) { RL_CHECK_SIGNALS (); - ret = noninc_search_from_pos (history_search_string, rl_history_search_pos + dir, dir); + ret = noninc_search_from_pos (history_search_string, rl_history_search_pos + dir, dir, 0, &newcol); if (ret == -1) break; @@ -512,12 +540,17 @@ rl_history_search_internal (count, dir) /* Copy the line we found into the current line buffer. */ make_history_line_current (temp); + /* decide where to put rl_point -- need to change this for pattern search */ if (rl_history_search_flags & ANCHORED_SEARCH) rl_point = rl_history_search_len; /* easy case */ else { - t = strstr (rl_line_buffer, history_search_string); +#if 0 + t = strstr (rl_line_buffer, history_search_string); /* XXX */ rl_point = t ? (int)(t - rl_line_buffer) + rl_history_search_len : rl_end; +#else + rl_point = (newcol >= 0) ? newcol : rl_end; +#endif } rl_mark = rl_end; @@ -525,8 +558,7 @@ rl_history_search_internal (count, dir) } static void -rl_history_search_reinit (flags) - int flags; +rl_history_search_reinit (int flags) { int sind; @@ -556,8 +588,7 @@ rl_history_search_reinit (flags) from the start of the line to rl_point. This is a non-incremental search. The search is anchored to the beginning of the history line. */ int -rl_history_search_forward (count, ignore) - int count, ignore; +rl_history_search_forward (int count, int ignore) { if (count == 0) return (0); @@ -575,8 +606,7 @@ rl_history_search_forward (count, ignore) from the start of the line to rl_point. This is a non-incremental search. */ int -rl_history_search_backward (count, ignore) - int count, ignore; +rl_history_search_backward (int count, int ignore) { if (count == 0) return (0); @@ -595,8 +625,7 @@ rl_history_search_backward (count, ignore) search. The search succeeds if the search string is present anywhere in the history line. */ int -rl_history_substr_search_forward (count, ignore) - int count, ignore; +rl_history_substr_search_forward (int count, int ignore) { if (count == 0) return (0); @@ -614,8 +643,7 @@ rl_history_substr_search_forward (count, ignore) from the start of the line to rl_point. This is a non-incremental search. */ int -rl_history_substr_search_backward (count, ignore) - int count, ignore; +rl_history_substr_search_backward (int count, int ignore) { if (count == 0) return (0); diff --git a/lib/readline/shell.c b/lib/readline/shell.c index 6947295e..7fe2e97c 100644 --- a/lib/readline/shell.c +++ b/lib/readline/shell.c @@ -1,7 +1,7 @@ /* shell.c -- readline utility functions that are normally provided by bash when readline is linked as part of the shell. */ -/* Copyright (C) 1997-2009 Free Software Foundation, Inc. +/* Copyright (C) 1997-2009,2017 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. @@ -92,8 +92,7 @@ extern struct passwd *getpwuid PARAMS((uid_t)); /* Does shell-like quoting using single quotes. */ char * -sh_single_quote (string) - char *string; +sh_single_quote (char *string) { register int c; char *result, *r, *s; @@ -127,8 +126,7 @@ static char putenv_buf1[INT_STRLEN_BOUND (int) + 6 + 1]; /* sizeof("LINES=") == static char putenv_buf2[INT_STRLEN_BOUND (int) + 8 + 1]; /* sizeof("COLUMNS=") == 8 */ void -sh_set_lines_and_columns (lines, cols) - int lines, cols; +sh_set_lines_and_columns (int lines, int cols) { #if defined (HAVE_SETENV) sprintf (setenv_buf, "%d", lines); @@ -148,14 +146,13 @@ sh_set_lines_and_columns (lines, cols) } char * -sh_get_env_value (varname) - const char *varname; +sh_get_env_value (const char *varname) { return ((char *)getenv (varname)); } char * -sh_get_home_dir () +sh_get_home_dir (void) { static char *home_dir = (char *)NULL; struct passwd *entry; @@ -188,8 +185,7 @@ sh_get_home_dir () #endif int -sh_unset_nodelay_mode (fd) - int fd; +sh_unset_nodelay_mode (int fd) { #if defined (HAVE_FCNTL) int flags, bflags; diff --git a/lib/readline/signals.c b/lib/readline/signals.c index 927f5323..76c5c473 100644 --- a/lib/readline/signals.c +++ b/lib/readline/signals.c @@ -1,6 +1,6 @@ /* signals.c -- signal handling support for readline. */ -/* Copyright (C) 1987-2016 Free Software Foundation, Inc. +/* Copyright (C) 1987-2017 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. @@ -113,6 +113,10 @@ int _rl_susp_char = 0; static int signals_set_flag; static int sigwinch_set_flag; +#if defined (HAVE_POSIX_SIGNALS) +sigset_t _rl_orig_sigset; +#endif /* !HAVE_POSIX_SIGNALS */ + /* **************************************************************** */ /* */ /* Signal Handling */ @@ -134,8 +138,7 @@ void *_rl_sigcleanarg; /* Called from RL_CHECK_SIGNALS() macro */ RETSIGTYPE -_rl_signal_handler (sig) - int sig; +_rl_signal_handler (int sig) { _rl_caught_signal = 0; /* XXX */ @@ -158,8 +161,7 @@ _rl_signal_handler (sig) } static RETSIGTYPE -rl_signal_handler (sig) - int sig; +rl_signal_handler (int sig) { if (_rl_interrupt_immediately) { @@ -173,8 +175,7 @@ rl_signal_handler (sig) } static RETSIGTYPE -_rl_handle_signal (sig) - int sig; +_rl_handle_signal (int sig) { #if defined (HAVE_POSIX_SIGNALS) sigset_t set; @@ -248,9 +249,11 @@ _rl_handle_signal (sig) rl_cleanup_after_signal (); #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 sigemptyset (&set); sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &set); @@ -289,8 +292,7 @@ _rl_handle_signal (sig) #if defined (SIGWINCH) static RETSIGTYPE -rl_sigwinch_handler (sig) - int sig; +rl_sigwinch_handler (int sig) { SigHandler *oh; @@ -321,9 +323,7 @@ rl_sigwinch_handler (sig) #if !defined (HAVE_POSIX_SIGNALS) static int -rl_sigaction (sig, nh, oh) - int sig; - sighandler_cxt *nh, *oh; +rl_sigaction (int sig, sighandler_cxt *nh, sighandler_cxt *oh) { oh->sa_handler = signal (sig, nh->sa_handler); return 0; @@ -334,10 +334,7 @@ rl_sigaction (sig, nh, oh) information in OHANDLER. Return the old signal handler, like signal(). */ static SigHandler * -rl_set_sighandler (sig, handler, ohandler) - int sig; - SigHandler *handler; - sighandler_cxt *ohandler; +rl_set_sighandler (int sig, SigHandler *handler, sighandler_cxt *ohandler) { sighandler_cxt old_handler; #if defined (HAVE_POSIX_SIGNALS) @@ -368,10 +365,7 @@ rl_set_sighandler (sig, handler, ohandler) /* Set disposition of SIG to HANDLER, returning old state in OHANDLER. Don't change disposition if OHANDLER indicates the signal was ignored. */ static void -rl_maybe_set_sighandler (sig, handler, ohandler) - int sig; - SigHandler *handler; - sighandler_cxt *ohandler; +rl_maybe_set_sighandler (int sig, SigHandler *handler, sighandler_cxt *ohandler) { sighandler_cxt dummy; SigHandler *oh; @@ -388,9 +382,7 @@ rl_maybe_set_sighandler (sig, handler, ohandler) disposition was changed using rl_maybe_set_sighandler or for which the SIG_IGN check was performed inline (e.g., SIGALRM below). */ static void -rl_maybe_restore_sighandler (sig, handler) - int sig; - sighandler_cxt *handler; +rl_maybe_restore_sighandler (int sig, sighandler_cxt *handler) { sighandler_cxt dummy; @@ -401,7 +393,7 @@ rl_maybe_restore_sighandler (sig, handler) } int -rl_set_signals () +rl_set_signals (void) { sighandler_cxt dummy; SigHandler *oh; @@ -442,8 +434,8 @@ rl_set_signals () if (rl_catch_signals && signals_set_flag == 0) { #if defined (HAVE_POSIX_SIGNALS) - sigemptyset (&oset); - sigprocmask (SIG_BLOCK, &bset, &oset); + sigemptyset (&_rl_orig_sigset); + sigprocmask (SIG_BLOCK, &bset, &_rl_orig_sigset); #endif rl_maybe_set_sighandler (SIGINT, rl_signal_handler, &old_int); @@ -484,7 +476,14 @@ rl_set_signals () signals_set_flag = 1; #if defined (HAVE_POSIX_SIGNALS) - sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL); + sigprocmask (SIG_SETMASK, &_rl_orig_sigset, (sigset_t *)NULL); +#endif + } + else if (rl_catch_signals == 0) + { +#if defined (HAVE_POSIX_SIGNALS) + sigemptyset (&_rl_orig_sigset); + sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &_rl_orig_sigset); #endif } @@ -500,14 +499,12 @@ rl_set_signals () } int -rl_clear_signals () +rl_clear_signals (void) { sighandler_cxt dummy; if (rl_catch_signals && signals_set_flag == 1) { - sigemptyset (&dummy.sa_mask); - /* Since rl_maybe_set_sighandler doesn't override a SIG_IGN handler, we should in theory not have to restore a handler where old_xxx.sa_handler == SIG_IGN. That's what rl_maybe_restore_sighandler @@ -555,7 +552,7 @@ rl_clear_signals () /* Clean up the terminal and readline state after catching a signal, before resending it to the calling application. */ void -rl_cleanup_after_signal () +rl_cleanup_after_signal (void) { _rl_clean_up_for_exit (); if (rl_deprep_term_function) @@ -566,7 +563,7 @@ rl_cleanup_after_signal () /* Reset the terminal and readline state after a signal handler returns. */ void -rl_reset_after_signal () +rl_reset_after_signal (void) { if (rl_prep_term_function) (*rl_prep_term_function) (_rl_meta_flag); @@ -578,7 +575,7 @@ rl_reset_after_signal () numeric arguments in process) after catching a signal, before calling rl_cleanup_after_signal(). */ void -rl_free_line_state () +rl_free_line_state (void) { register HIST_ENTRY *entry; @@ -594,10 +591,16 @@ rl_free_line_state () } int -rl_pending_signal () +rl_pending_signal (void) { return (_rl_caught_signal); } + +void +rl_check_signals (void) +{ + RL_CHECK_SIGNALS (); +} #endif /* HANDLE_SIGNALS */ /* **************************************************************** */ @@ -622,7 +625,7 @@ static int sigwinch_blocked; /* Cause SIGINT to not be delivered until the corresponding call to release_sigint(). */ void -_rl_block_sigint () +_rl_block_sigint (void) { if (sigint_blocked) return; @@ -632,7 +635,7 @@ _rl_block_sigint () /* Allow SIGINT to be delivered. */ void -_rl_release_sigint () +_rl_release_sigint (void) { if (sigint_blocked == 0) return; @@ -644,7 +647,7 @@ _rl_release_sigint () /* Cause SIGWINCH to not be delivered until the corresponding call to release_sigwinch(). */ void -_rl_block_sigwinch () +_rl_block_sigwinch (void) { if (sigwinch_blocked) return; @@ -673,7 +676,7 @@ _rl_block_sigwinch () /* Allow SIGWINCH to be delivered. */ void -_rl_release_sigwinch () +_rl_release_sigwinch (void) { if (sigwinch_blocked == 0) return; @@ -703,8 +706,7 @@ _rl_release_sigwinch () /* */ /* **************************************************************** */ void -rl_echo_signal_char (sig) - int sig; +rl_echo_signal_char (int sig) { char cstr[3]; int cslen, c; diff --git a/lib/readline/terminal.c b/lib/readline/terminal.c index ef2884e0..d9a6a999 100644 --- a/lib/readline/terminal.c +++ b/lib/readline/terminal.c @@ -1,6 +1,6 @@ /* terminal.c -- controlling the terminal with termcap. */ -/* Copyright (C) 1996-2015 Free Software Foundation, Inc. +/* Copyright (C) 1996-2017 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. @@ -112,6 +112,7 @@ char PC, *BC, *UP; /* Some strings to control terminal actions. These are output by tputs (). */ char *_rl_term_clreol; char *_rl_term_clrpag; +char *_rl_term_clrscroll; char *_rl_term_cr; char *_rl_term_backspace; char *_rl_term_goto; @@ -131,6 +132,7 @@ char *_rl_term_IC; char *_rl_term_dc; char *_rl_term_DC; +/* How to move forward a char, non-destructively */ char *_rl_term_forward_char; /* How to go up a line. */ @@ -188,8 +190,7 @@ int _rl_enable_meta = 1; #if defined (__EMX__) static void -_emx_get_screensize (swp, shp) - int *swp, *shp; +_emx_get_screensize (int *swp, int *shp) { int sz[2]; @@ -204,8 +205,7 @@ _emx_get_screensize (swp, shp) #if defined (__MINGW32__) static void -_win_get_screensize (swp, shp) - int *swp, *shp; +_win_get_screensize (int *swp, int *shp) { HANDLE hConOut; CONSOLE_SCREEN_BUFFER_INFO scr; @@ -227,8 +227,7 @@ _win_get_screensize (swp, shp) values of $LINES and $COLUMNS. The tests for TERM_STRING_BUFFER being non-null serve to check whether or not we have initialized termcap. */ void -_rl_get_screen_size (tty, ignore_env) - int tty, ignore_env; +_rl_get_screen_size (int tty, int ignore_env) { char *ss; #if defined (TIOCGWINSZ) @@ -318,8 +317,7 @@ _rl_get_screen_size (tty, ignore_env) } void -_rl_set_screen_size (rows, cols) - int rows, cols; +_rl_set_screen_size (int rows, int cols) { if (_rl_term_autowrap == -1) _rl_init_terminal_io (rl_terminal_name); @@ -338,15 +336,13 @@ _rl_set_screen_size (rows, cols) } void -rl_set_screen_size (rows, cols) - int rows, cols; +rl_set_screen_size (int rows, int cols) { _rl_set_screen_size (rows, cols); } void -rl_get_screen_size (rows, cols) - int *rows, *cols; +rl_get_screen_size (int *rows, int *cols) { if (rows) *rows = _rl_screenheight; @@ -355,19 +351,19 @@ rl_get_screen_size (rows, cols) } void -rl_reset_screen_size () +rl_reset_screen_size (void) { _rl_get_screen_size (fileno (rl_instream), 0); } void -_rl_sigwinch_resize_terminal () +_rl_sigwinch_resize_terminal (void) { _rl_get_screen_size (fileno (rl_instream), 1); } void -rl_resize_terminal () +rl_resize_terminal (void) { _rl_get_screen_size (fileno (rl_instream), 1); if (_rl_echoing_p) @@ -390,6 +386,7 @@ static const struct _tc_string tc_strings[] = { { "@7", &_rl_term_at7 }, { "DC", &_rl_term_DC }, + { "E3", &_rl_term_clrscroll }, { "IC", &_rl_term_IC }, { "ce", &_rl_term_clreol }, { "cl", &_rl_term_clrpag }, @@ -424,8 +421,7 @@ static const struct _tc_string tc_strings[] = /* Read the desired terminal capability strings into BP. The capabilities are described in the TC_STRINGS table. */ static void -get_term_capabilities (bp) - char **bp; +get_term_capabilities (char **bp) { #if !defined (__DJGPP__) /* XXX - doesn't DJGPP have a termcap library? */ register int i; @@ -437,15 +433,14 @@ get_term_capabilities (bp) } int -_rl_init_terminal_io (terminal_name) - const char *terminal_name; +_rl_init_terminal_io (const char *terminal_name) { const char *term; char *buffer; int tty, tgetent_ret; term = terminal_name ? terminal_name : sh_get_env_value ("TERM"); - _rl_term_clrpag = _rl_term_cr = _rl_term_clreol = (char *)NULL; + _rl_term_clrpag = _rl_term_cr = _rl_term_clreol = _rl_term_clrscroll = (char *)NULL; tty = rl_instream ? fileno (rl_instream) : 0; if (term == 0) @@ -458,7 +453,7 @@ _rl_init_terminal_io (terminal_name) _rl_term_mm = _rl_term_mo = (char *)NULL; _rl_terminal_can_insert = term_has_meta = _rl_term_autowrap = 0; _rl_term_cr = "\r"; - _rl_term_clreol = _rl_term_clrpag = _rl_term_backspace = (char *)NULL; + _rl_term_backspace = (char *)NULL; _rl_term_goto = _rl_term_pc = _rl_term_ip = (char *)NULL; _rl_term_ks = _rl_term_ke =_rl_term_vs = _rl_term_ve = (char *)NULL; _rl_term_kh = _rl_term_kH = _rl_term_at7 = _rl_term_kI = (char *)NULL; @@ -584,8 +579,7 @@ _rl_init_terminal_io (terminal_name) /* Bind the arrow key sequences from the termcap description in MAP. */ static void -bind_termcap_arrow_keys (map) - Keymap map; +bind_termcap_arrow_keys (Keymap map) { Keymap xkeymap; @@ -606,8 +600,7 @@ bind_termcap_arrow_keys (map) } char * -rl_get_termcap (cap) - const char *cap; +rl_get_termcap (const char *cap) { register int i; @@ -624,8 +617,7 @@ rl_get_termcap (cap) /* Re-initialize the terminal considering that the TERM/TERMCAP variable has changed. */ int -rl_reset_terminal (terminal_name) - const char *terminal_name; +rl_reset_terminal (const char *terminal_name) { _rl_screenwidth = _rl_screenheight = 0; _rl_init_terminal_io (terminal_name); @@ -635,15 +627,13 @@ rl_reset_terminal (terminal_name) /* A function for the use of tputs () */ #ifdef _MINIX void -_rl_output_character_function (c) - int c; +_rl_output_character_function (int c) { putc (c, _rl_out_stream); } #else /* !_MINIX */ int -_rl_output_character_function (c) - int c; +_rl_output_character_function (int c) { return putc (c, _rl_out_stream); } @@ -651,17 +641,14 @@ _rl_output_character_function (c) /* Write COUNT characters from STRING to the output stream. */ void -_rl_output_some_chars (string, count) - const char *string; - int count; +_rl_output_some_chars (const char *string, int count) { fwrite (string, 1, count, _rl_out_stream); } /* Move the cursor back. */ int -_rl_backspace (count) - int count; +_rl_backspace (int count) { register int i; @@ -678,7 +665,7 @@ _rl_backspace (count) /* Move to the start of the next line. */ int -rl_crlf () +rl_crlf (void) { #if defined (NEW_TTY_DRIVER) || defined (__MINT__) if (_rl_term_cr) @@ -690,7 +677,7 @@ rl_crlf () /* Ring the terminal bell. */ int -rl_ding () +rl_ding (void) { if (_rl_echoing_p) { @@ -729,7 +716,7 @@ rl_ding () static int enabled_meta = 0; /* flag indicating we enabled meta mode */ void -_rl_enable_meta_key () +_rl_enable_meta_key (void) { #if !defined (__DJGPP__) if (term_has_meta && _rl_term_mm) @@ -741,7 +728,7 @@ _rl_enable_meta_key () } void -_rl_disable_meta_key () +_rl_disable_meta_key (void) { #if !defined (__DJGPP__) if (term_has_meta && _rl_term_mo && enabled_meta) @@ -753,8 +740,7 @@ _rl_disable_meta_key () } void -_rl_control_keypad (on) - int on; +_rl_control_keypad (int on) { #if !defined (__DJGPP__) if (on && _rl_term_ks) @@ -775,8 +761,7 @@ _rl_control_keypad (on) cursor. Overwrite mode gets a very visible cursor. Only does anything if we have both capabilities. */ void -_rl_set_cursor (im, force) - int im, force; +_rl_set_cursor (int im, int force) { #ifndef __MSDOS__ if (_rl_term_ve && _rl_term_vs) diff --git a/lib/readline/text.c b/lib/readline/text.c index c353252b..81de2a99 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-2016 Free Software Foundation, Inc. +/* Copyright (C) 1987-2017 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. @@ -83,8 +83,7 @@ int _rl_optimize_typeahead = 1; /* rl_insert tries to read typeahead */ way that you should do insertion. _rl_insert_char () calls this function. Returns the number of characters inserted. */ int -rl_insert_text (string) - const char *string; +rl_insert_text (const char *string) { register int i, l; @@ -121,8 +120,7 @@ rl_insert_text (string) /* Delete the string between FROM and TO. FROM is inclusive, TO is not. Returns the number of characters deleted. */ int -rl_delete_text (from, to) - int from, to; +rl_delete_text (int from, int to) { register char *text; register int diff, i; @@ -172,8 +170,7 @@ rl_delete_text (from, to) } while (0) void -_rl_fix_point (fix_mark_too) - int fix_mark_too; +_rl_fix_point (int fix_mark_too) { _RL_FIX_POINT (rl_point); if (fix_mark_too) @@ -185,9 +182,7 @@ _rl_fix_point (fix_mark_too) TEXT. The operation is undoable. To replace the entire line in an undoable mode, use _rl_replace_text(text, 0, rl_end); */ int -_rl_replace_text (text, start, end) - const char *text; - int start, end; +_rl_replace_text (const char *text, int start, int end) { int n; @@ -206,9 +201,7 @@ _rl_replace_text (text, start, end) /* Replace the current line buffer contents with TEXT. If CLEAR_UNDO is non-zero, we free the current undo list. */ void -rl_replace_line (text, clear_undo) - const char *text; - int clear_undo; +rl_replace_line (const char *text, int clear_undo) { int len; @@ -259,8 +252,7 @@ rl_replace_line (text, clear_undo) /* Move forward COUNT bytes. */ int -rl_forward_byte (count, key) - int count, key; +rl_forward_byte (int count, int key) { if (count < 0) return (rl_backward_byte (-count, key)); @@ -292,8 +284,7 @@ rl_forward_byte (count, key) } int -_rl_forward_char_internal (count) - int count; +_rl_forward_char_internal (int count) { int point; @@ -319,8 +310,7 @@ _rl_forward_char_internal (count) #if defined (HANDLE_MULTIBYTE) /* Move forward COUNT characters. */ int -rl_forward_char (count, key) - int count, key; +rl_forward_char (int count, int key) { int point; @@ -350,8 +340,7 @@ rl_forward_char (count, key) } #else /* !HANDLE_MULTIBYTE */ int -rl_forward_char (count, key) - int count, key; +rl_forward_char (int count, int key) { return (rl_forward_byte (count, key)); } @@ -359,16 +348,14 @@ rl_forward_char (count, key) /* Backwards compatibility. */ int -rl_forward (count, key) - int count, key; +rl_forward (int count, int key) { return (rl_forward_char (count, key)); } /* Move backward COUNT bytes. */ int -rl_backward_byte (count, key) - int count, key; +rl_backward_byte (int count, int key) { if (count < 0) return (rl_forward_byte (-count, key)); @@ -393,8 +380,7 @@ rl_backward_byte (count, key) #if defined (HANDLE_MULTIBYTE) /* Move backward COUNT characters. */ int -rl_backward_char (count, key) - int count, key; +rl_backward_char (int count, int key) { int point; @@ -426,8 +412,7 @@ rl_backward_char (count, key) } #else int -rl_backward_char (count, key) - int count, key; +rl_backward_char (int count, int key) { return (rl_backward_byte (count, key)); } @@ -435,16 +420,14 @@ rl_backward_char (count, key) /* Backwards compatibility. */ int -rl_backward (count, key) - int count, key; +rl_backward (int count, int key) { return (rl_backward_char (count, key)); } /* Move to the beginning of the line. */ int -rl_beg_of_line (count, key) - int count, key; +rl_beg_of_line (int count, int key) { rl_point = 0; return 0; @@ -452,8 +435,7 @@ rl_beg_of_line (count, key) /* Move to the end of the line. */ int -rl_end_of_line (count, key) - int count, key; +rl_end_of_line (int count, int key) { rl_point = rl_end; return 0; @@ -461,8 +443,7 @@ rl_end_of_line (count, key) /* Move forward a word. We do what Emacs does. Handles multibyte chars. */ int -rl_forward_word (count, key) - int count, key; +rl_forward_word (int count, int key) { int c; @@ -510,8 +491,7 @@ rl_forward_word (count, key) /* Move backward a word. We do what Emacs does. Handles multibyte chars. */ int -rl_backward_word (count, key) - int count, key; +rl_backward_word (int count, int key) { int c, p; @@ -560,8 +540,7 @@ rl_backward_word (count, key) /* Clear the current line. Numeric argument to C-l does this. */ int -rl_refresh_line (ignore1, ignore2) - int ignore1, ignore2; +rl_refresh_line (int ignore1, int ignore2) { int curr_line; @@ -582,8 +561,7 @@ rl_refresh_line (ignore1, ignore2) the prompt and the current input line. Given a numeric arg, redraw only the current line. */ int -rl_clear_screen (count, key) - int count, key; +rl_clear_screen (int count, int key) { if (rl_explicit_arg) { @@ -599,8 +577,25 @@ rl_clear_screen (count, key) } int -rl_skip_csi_sequence (count, key) - int count, key; +rl_previous_screen_line (int count, int key) +{ + int c; + + c = _rl_term_autowrap ? _rl_screenwidth : (_rl_screenwidth + 1); + return (rl_backward_char (c, key)); +} + +int +rl_next_screen_line (int count, int key) +{ + int c; + + c = _rl_term_autowrap ? _rl_screenwidth : (_rl_screenwidth + 1); + return (rl_forward_char (c, key)); +} + +int +rl_skip_csi_sequence (int count, int key) { int ch; @@ -614,8 +609,7 @@ rl_skip_csi_sequence (count, key) } int -rl_arrow_keys (count, c) - int count, c; +rl_arrow_keys (int count, int key) { int ch; @@ -672,8 +666,7 @@ static mbstate_t ps = {0}; If C introduces a multibyte sequence, we read the whole sequence and then insert the multibyte char into the line buffer. */ int -_rl_insert_char (count, c) - int count, c; +_rl_insert_char (int count, int c) { register int i; char *string; @@ -695,6 +688,12 @@ _rl_insert_char (count, c) incoming[1] = '\0'; incoming_length = 1; } + else if (_rl_utf8locale && (c & 0x80) == 0) + { + incoming[0] = c; + incoming[1] = '\0'; + incoming_length = 1; + } else { wchar_t wc; @@ -739,6 +738,12 @@ _rl_insert_char (count, c) effect of mbstate is undefined. */ memset (&ps, 0, sizeof (mbstate_t)); } + else if (ret == 1) + { + incoming[0] = pending_bytes[0]; + incoming[incoming_length = 1] = '\0'; + pending_bytes_length = 0; + } else { /* We successfully read a single multibyte character. */ @@ -761,8 +766,13 @@ _rl_insert_char (count, c) i = 0; while (i < string_size) { - strncpy (string + i, incoming, incoming_length); - i += incoming_length; + if (incoming_length == 1) + string[i++] = *incoming; + else + { + strncpy (string + i, incoming, incoming_length); + i += incoming_length; + } } incoming_length = 0; stored_count = 0; @@ -790,8 +800,13 @@ _rl_insert_char (count, c) i = 0; while (i < string_size) { - strncpy (string + i, incoming, incoming_length); - i += incoming_length; + if (incoming_length == 1) + string[i++] = *incoming; + else + { + strncpy (string + i, incoming, incoming_length); + i += incoming_length; + } } while (count) @@ -857,8 +872,7 @@ _rl_insert_char (count, c) If C introduces a multibyte character sequence, read the entire sequence before starting the overwrite loop. */ int -_rl_overwrite_char (count, c) - int count, c; +_rl_overwrite_char (int count, int c) { int i; #if defined (HANDLE_MULTIBYTE) @@ -891,8 +905,7 @@ _rl_overwrite_char (count, c) } int -rl_insert (count, c) - int count, c; +rl_insert (int count, int c) { int r, n, x; @@ -902,6 +915,7 @@ rl_insert (count, c) x = 0; n = (unsigned short)-2; while (_rl_optimize_typeahead && + rl_num_chars_to_read == 0 && (RL_ISSTATE (RL_STATE_INPUTPENDING|RL_STATE_MACROINPUT) == 0) && _rl_pushed_input_available () == 0 && _rl_input_queued (0) && @@ -941,8 +955,7 @@ rl_insert (count, c) /* Insert the next typed character verbatim. */ static int -_rl_insert_next (count) - int count; +_rl_insert_next (int count) { int c; @@ -966,24 +979,37 @@ _rl_insert_next (count) #if defined (READLINE_CALLBACKS) static int -_rl_insert_next_callback (data) - _rl_callback_generic_arg *data; +_rl_insert_next_callback (_rl_callback_generic_arg *data) { - int count; + int count, r; count = data->count; + r = 0; + + if (count < 0) + { + data->count++; + r = _rl_insert_next (1); + _rl_want_redisplay = 1; + /* If we should keep going, leave the callback function installed */ + if (data->count < 0 && r == 0) + return r; + count = 0; /* data->count == 0 || r != 0; force break below */ + } /* Deregister function, let rl_callback_read_char deallocate data */ _rl_callback_func = 0; _rl_want_redisplay = 1; - + + if (count == 0) + return r; + return _rl_insert_next (count); } #endif int -rl_quoted_insert (count, key) - int count, key; +rl_quoted_insert (int count, int key) { /* Let's see...should the callback interface futz with signal handling? */ #if defined (HANDLE_SIGNALS) @@ -999,14 +1025,24 @@ rl_quoted_insert (count, key) return (0); } #endif - + + /* A negative count means to quote the next -COUNT characters. */ + if (count < 0) + { + int r; + + do + r = _rl_insert_next (1); + while (r == 0 && ++count < 0); + return r; + } + return _rl_insert_next (count); } /* Insert a tab character. */ int -rl_tab_insert (count, key) - int count, key; +rl_tab_insert (int count, int key) { return (_rl_insert_char (count, '\t')); } @@ -1015,8 +1051,7 @@ rl_tab_insert (count, key) KEY is the key that invoked this command. I guess it could have meaning in the future. */ int -rl_newline (count, key) - int count, key; +rl_newline (int count, int key) { rl_done = 1; @@ -1049,8 +1084,7 @@ rl_newline (count, key) is just a stub, you bind keys to it and the code in _rl_dispatch () is special cased. */ int -rl_do_lowercase_version (ignore1, ignore2) - int ignore1, ignore2; +rl_do_lowercase_version (int ignore1, int ignore2) { return 0; } @@ -1059,8 +1093,7 @@ rl_do_lowercase_version (ignore1, ignore2) rubout in overwrite mode has one oddity: it replaces a control character that's displayed as two characters (^X) with two spaces. */ int -_rl_overwrite_rubout (count, key) - int count, key; +_rl_overwrite_rubout (int count, int key) { int opoint; int i, l; @@ -1102,8 +1135,7 @@ _rl_overwrite_rubout (count, key) /* Rubout the character behind point. */ int -rl_rubout (count, key) - int count, key; +rl_rubout (int count, int key) { if (count < 0) return (rl_delete (-count, key)); @@ -1121,8 +1153,7 @@ rl_rubout (count, key) } int -_rl_rubout_char (count, key) - int count, key; +_rl_rubout_char (int count, int key) { int orig_point; unsigned char c; @@ -1167,8 +1198,7 @@ _rl_rubout_char (count, key) /* Delete the character under the cursor. Given a numeric argument, kill that many characters instead. */ int -rl_delete (count, key) - int count, key; +rl_delete (int count, int key) { int xpoint; @@ -1205,8 +1235,7 @@ rl_delete (count, key) behind the cursor is deleted. COUNT is obeyed and may be used to delete forward or backward that many characters. */ int -rl_rubout_or_delete (count, key) - int count, key; +rl_rubout_or_delete (int count, int key) { if (rl_end != 0 && rl_point == rl_end) return (_rl_rubout_char (count, key)); @@ -1216,8 +1245,7 @@ rl_rubout_or_delete (count, key) /* Delete all spaces and tabs around point. */ int -rl_delete_horizontal_space (count, ignore) - int count, ignore; +rl_delete_horizontal_space (int count, int ignore) { int start; @@ -1245,8 +1273,7 @@ rl_delete_horizontal_space (count, ignore) is caught before this is invoked, so this really does the same thing as delete-char-or-list-or-eof, as long as it's bound to the eof character. */ int -rl_delete_or_show_completions (count, key) - int count, key; +rl_delete_or_show_completions (int count, int key) { if (rl_end != 0 && rl_point == rl_end) return (rl_possible_completions (count, key)); @@ -1261,8 +1288,7 @@ rl_delete_or_show_completions (count, key) /* Turn the current line into a comment in shell history. A K*rn shell style function. */ int -rl_insert_comment (count, key) - int count, key; +rl_insert_comment (int count, int key) { char *rl_comment_text; int rl_comment_len; @@ -1300,24 +1326,21 @@ rl_insert_comment (count, key) /* Uppercase the word at point. */ int -rl_upcase_word (count, key) - int count, key; +rl_upcase_word (int count, int key) { return (rl_change_case (count, UpCase)); } /* Lowercase the word at point. */ int -rl_downcase_word (count, key) - int count, key; +rl_downcase_word (int count, int key) { return (rl_change_case (count, DownCase)); } /* Upcase the first letter, downcase the rest. */ int -rl_capitalize_word (count, key) - int count, key; +rl_capitalize_word (int count, int key) { return (rl_change_case (count, CapCase)); } @@ -1328,11 +1351,11 @@ rl_capitalize_word (count, key) If a negative argument is given, leave point where it started, otherwise, leave it where it moves to. */ static int -rl_change_case (count, op) - int count, op; +rl_change_case (int count, int op) { int start, next, end; - int inword, c, nc, nop; + int inword, nc, nop; + wchar_t c; #if defined (HANDLE_MULTIBYTE) wchar_t wc, nwc; char mb[MB_LEN_MAX+1]; @@ -1382,7 +1405,10 @@ rl_change_case (count, op) } else nop = op; - if (MB_CUR_MAX == 1 || rl_byte_oriented || isascii ((unsigned char)c)) + /* Can't check isascii here; some languages (e.g, Turkish) have + multibyte upper and lower case equivalents of single-byte ascii + characters */ + if (MB_CUR_MAX == 1 || rl_byte_oriented) { nc = (nop == UpCase) ? _rl_to_upper (c) : _rl_to_lower (c); rl_line_buffer[start] = nc; @@ -1398,11 +1424,35 @@ rl_change_case (count, op) nwc = (nop == UpCase) ? _rl_to_wupper (wc) : _rl_to_wlower (wc); if (nwc != wc) /* just skip unchanged characters */ { + char *s, *e; mlen = wcrtomb (mb, nwc, &mps); if (mlen > 0) mb[mlen] = '\0'; - /* Assume the same width */ - strncpy (rl_line_buffer + start, mb, mlen); + /* what to do if m != mlen? adjust below */ + /* m == length of old char, mlen == length of new char */ + s = rl_line_buffer + start; + e = rl_line_buffer + rl_end; + if (m == mlen) + memcpy (s, mb, mlen); + else if (m > mlen) + { + memcpy (s, mb, mlen); + memmove (s + mlen, s + m, (e - s) - m); + next -= m - mlen; /* next char changes */ + end -= m - mlen; /* end of word changes */ + rl_end -= m - mlen; /* end of line changes */ + rl_line_buffer[rl_end] = 0; + } + else if (m < mlen) + { + rl_extend_line_buffer (mlen - m + 1); + memmove (s + mlen, s + m, (e - s) - m); + memcpy (s, mb, mlen); + next += mlen - m; /* next char changes */ + end += mlen - m; /* end of word changes */ + rl_end += mlen - m; /* end of line changes */ + rl_line_buffer[rl_end] = 0; + } } } #endif @@ -1423,8 +1473,7 @@ rl_change_case (count, op) /* Transpose the words at point. If point is at the end of the line, transpose the two words before point. */ int -rl_transpose_words (count, key) - int count, key; +rl_transpose_words (int count, int key) { char *word1, *word2; int w1_beg, w1_end, w2_beg, w2_end; @@ -1484,8 +1533,7 @@ rl_transpose_words (count, key) /* Transpose the characters at point. If point is at the end of the line, then transpose the characters before point. */ int -rl_transpose_chars (count, key) - int count, key; +rl_transpose_chars (int count, int key) { #if defined (HANDLE_MULTIBYTE) char *dummy; @@ -1549,13 +1597,9 @@ rl_transpose_chars (count, key) int #if defined (HANDLE_MULTIBYTE) -_rl_char_search_internal (count, dir, smbchar, len) - int count, dir; - char *smbchar; - int len; +_rl_char_search_internal (int count, int dir, char *smbchar, int len) #else -_rl_char_search_internal (count, dir, schar) - int count, dir, schar; +_rl_char_search_internal (int count, int dir, int schar) #endif { int pos, inc; @@ -1619,8 +1663,7 @@ _rl_char_search_internal (count, dir, schar) that there are two separate versions of this function. */ #if defined (HANDLE_MULTIBYTE) static int -_rl_char_search (count, fdir, bdir) - int count, fdir, bdir; +_rl_char_search (int count, int fdir, int bdir) { char mbchar[MB_LEN_MAX]; int mb_len; @@ -1637,8 +1680,7 @@ _rl_char_search (count, fdir, bdir) } #else /* !HANDLE_MULTIBYTE */ static int -_rl_char_search (count, fdir, bdir) - int count, fdir, bdir; +_rl_char_search (int count, int fdir, int bdir) { int c; @@ -1669,8 +1711,7 @@ _rl_char_search_callback (data) #endif int -rl_char_search (count, key) - int count, key; +rl_char_search (int count, int key) { #if defined (READLINE_CALLBACKS) if (RL_ISSTATE (RL_STATE_CALLBACK)) @@ -1687,8 +1728,7 @@ rl_char_search (count, key) } int -rl_backward_char_search (count, key) - int count, key; +rl_backward_char_search (int count, int key) { #if defined (READLINE_CALLBACKS) if (RL_ISSTATE (RL_STATE_CALLBACK)) @@ -1712,10 +1752,9 @@ rl_backward_char_search (count, key) /* Set the mark at POSITION. */ int -_rl_set_mark_at_pos (position) - int position; +_rl_set_mark_at_pos (int position) { - if (position > rl_end) + if (position < 0 || position > rl_end) return 1; rl_mark = position; @@ -1724,23 +1763,22 @@ _rl_set_mark_at_pos (position) /* A bindable command to set the mark. */ int -rl_set_mark (count, key) - int count, key; +rl_set_mark (int count, int key) { return (_rl_set_mark_at_pos (rl_explicit_arg ? count : rl_point)); } /* Exchange the position of mark and point. */ int -rl_exchange_point_and_mark (count, key) - int count, key; +rl_exchange_point_and_mark (int count, int key) { if (rl_mark > rl_end) rl_mark = -1; - if (rl_mark == -1) + if (rl_mark < 0) { rl_ding (); + rl_mark = 0; /* like _RL_FIX_POINT */ return 1; } else diff --git a/lib/readline/tilde.c b/lib/readline/tilde.c index 95bc4215..9d0f2961 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-2009 Free Software Foundation, Inc. +/* Copyright (C) 1988-2017 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. @@ -125,9 +125,7 @@ static char *glue_prefix_and_suffix PARAMS((char *, const char *, int)); the tilde which starts the expansion. Place the length of the text which identified this tilde starter in LEN, excluding the tilde itself. */ static int -tilde_find_prefix (string, len) - const char *string; - int *len; +tilde_find_prefix (const char *string, int *len) { register int i, j, string_len; register char **prefixes; @@ -160,8 +158,7 @@ tilde_find_prefix (string, len) /* Find the end of a tilde expansion in STRING, and return the index of the character which ends the tilde definition. */ static int -tilde_find_suffix (string) - const char *string; +tilde_find_suffix (const char *string) { register int i, j, string_len; register char **suffixes; @@ -189,8 +186,7 @@ tilde_find_suffix (string) /* Return a new string which is the result of tilde expanding STRING. */ char * -tilde_expand (string) - const char *string; +tilde_expand (const char *string) { char *result; int result_size, result_index; @@ -267,9 +263,7 @@ tilde_expand (string) non-null, the index of the end of the prefix into FNAME is returned in the location it points to. */ static char * -isolate_tilde_prefix (fname, lenp) - const char *fname; - int *lenp; +isolate_tilde_prefix (const char *fname, int *lenp) { char *ret; int i; @@ -293,9 +287,7 @@ isolate_tilde_prefix (fname, lenp) function. Right now, it just calls tilde_find_suffix and allocates new memory, but it can be expanded to do different things later. */ char * -tilde_find_word (fname, flags, lenp) - const char *fname; - int flags, *lenp; +tilde_find_word (const char *fname, int flags, int *lenp) { int x; char *r; @@ -323,10 +315,7 @@ tilde_find_word (fname, flags, lenp) /* Return a string that is PREFIX concatenated with SUFFIX starting at SUFFIND. */ static char * -glue_prefix_and_suffix (prefix, suffix, suffind) - char *prefix; - const char *suffix; - int suffind; +glue_prefix_and_suffix (char *prefix, const char *suffix, int suffind) { char *ret; int plen, slen; @@ -344,8 +333,7 @@ glue_prefix_and_suffix (prefix, suffix, suffind) tilde. If there is no expansion, call tilde_expansion_failure_hook. This always returns a newly-allocated string, never static storage. */ char * -tilde_expand_word (filename) - const char *filename; +tilde_expand_word (const char *filename) { char *dirname, *expansion, *username; int user_len; @@ -434,9 +422,7 @@ tilde_expand_word (filename) #undef NULL #include <stdio.h> -main (argc, argv) - int argc; - char **argv; +main (int argc, char **argv) { char *result, line[512]; int done = 0; @@ -464,11 +450,10 @@ main (argc, argv) exit (0); } -static void memory_error_and_abort (); +static void memory_error_and_abort (void); static void * -xmalloc (bytes) - size_t bytes; +xmalloc (size_t bytes) { void *temp = (char *)malloc (bytes); @@ -478,9 +463,7 @@ xmalloc (bytes) } static void * -xrealloc (pointer, bytes) - void *pointer; - int bytes; +xrealloc (void *pointer, int bytes) { void *temp; @@ -496,7 +479,7 @@ xrealloc (pointer, bytes) } static void -memory_error_and_abort () +memory_error_and_abort (void) { fprintf (stderr, "readline: out of virtual memory\n"); abort (); diff --git a/lib/readline/undo.c b/lib/readline/undo.c index 58363040..75874e5d 100644 --- a/lib/readline/undo.c +++ b/lib/readline/undo.c @@ -1,6 +1,6 @@ /* undo.c - manage list of changes to lines, offering opportunity to undo them */ -/* Copyright (C) 1987-2015 Free Software Foundation, Inc. +/* Copyright (C) 1987-2017 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. @@ -68,10 +68,7 @@ UNDO_LIST *rl_undo_list = (UNDO_LIST *)NULL; /* **************************************************************** */ static UNDO_LIST * -alloc_undo_entry (what, start, end, text) - enum undo_code what; - int start, end; - char *text; +alloc_undo_entry (enum undo_code what, int start, int end, char *text) { UNDO_LIST *temp; @@ -88,10 +85,7 @@ alloc_undo_entry (what, start, end, text) /* Remember how to undo something. Concatenate some undos if that seems right. */ void -rl_add_undo (what, start, end, text) - enum undo_code what; - int start, end; - char *text; +rl_add_undo (enum undo_code what, int start, int end, char *text) { UNDO_LIST *temp; @@ -102,8 +96,7 @@ rl_add_undo (what, start, end, text) /* Free an UNDO_LIST */ void -_rl_free_undo_list (ul) - UNDO_LIST *ul; +_rl_free_undo_list (UNDO_LIST *ul) { UNDO_LIST *release; @@ -121,7 +114,7 @@ _rl_free_undo_list (ul) /* Free the existing undo list. */ void -rl_free_undo_list () +rl_free_undo_list (void) { UNDO_LIST *release, *orig_list; @@ -132,8 +125,7 @@ rl_free_undo_list () } UNDO_LIST * -_rl_copy_undo_entry (entry) - UNDO_LIST *entry; +_rl_copy_undo_entry (UNDO_LIST *entry) { UNDO_LIST *new; @@ -143,8 +135,7 @@ _rl_copy_undo_entry (entry) } UNDO_LIST * -_rl_copy_undo_list (head) - UNDO_LIST *head; +_rl_copy_undo_list (UNDO_LIST *head) { UNDO_LIST *list, *new, *roving, *c; @@ -173,7 +164,7 @@ _rl_copy_undo_list (head) /* Undo the next thing in the list. Return 0 if there is nothing to undo, or non-zero if there was. */ int -rl_do_undo () +rl_do_undo (void) { UNDO_LIST *release; int waiting_for_begin, start, end; @@ -255,8 +246,7 @@ rl_do_undo () #undef TRANS int -_rl_fix_last_undo_of_type (type, start, end) - int type, start, end; +_rl_fix_last_undo_of_type (int type, int start, int end) { UNDO_LIST *rl; @@ -274,7 +264,7 @@ _rl_fix_last_undo_of_type (type, start, end) /* Begin a group. Subsequent undos are undone as an atomic operation. */ int -rl_begin_undo_group () +rl_begin_undo_group (void) { rl_add_undo (UNDO_BEGIN, 0, 0, 0); _rl_undo_group_level++; @@ -283,7 +273,7 @@ rl_begin_undo_group () /* End an undo group started with rl_begin_undo_group (). */ int -rl_end_undo_group () +rl_end_undo_group (void) { rl_add_undo (UNDO_END, 0, 0, 0); _rl_undo_group_level--; @@ -292,8 +282,7 @@ rl_end_undo_group () /* Save an undo entry for the text from START to END. */ int -rl_modifying (start, end) - int start, end; +rl_modifying (int start, int end) { if (start > end) { @@ -313,8 +302,7 @@ rl_modifying (start, end) /* Revert the current line to its previous state. */ int -rl_revert_line (count, key) - int count, key; +rl_revert_line (int count, int key) { if (rl_undo_list == 0) rl_ding (); @@ -333,8 +321,7 @@ rl_revert_line (count, key) /* Do some undoing of things that were done. */ int -rl_undo_command (count, key) - int count, key; +rl_undo_command (int count, int key) { if (count < 0) return 0; /* Nothing to do. */ diff --git a/lib/readline/util.c b/lib/readline/util.c index 4589c61f..e009b238 100644 --- a/lib/readline/util.c +++ b/lib/readline/util.c @@ -1,6 +1,6 @@ /* util.c -- readline utility functions */ -/* Copyright (C) 1987-2015 Free Software Foundation, Inc. +/* Copyright (C) 1987-2017 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. @@ -70,8 +70,7 @@ int _rl_allow_pathname_alphabetic_chars = 0; static const char * const pathname_alphabetic_chars = "/-_=~.#$"; int -rl_alphabetic (c) - int c; +rl_alphabetic (int c) { if (ALPHABETIC (c)) return (1); @@ -97,7 +96,7 @@ _rl_walphabetic (wchar_t wc) /* How to abort things. */ int -_rl_abort_internal () +_rl_abort_internal (void) { rl_ding (); rl_clear_message (); @@ -117,22 +116,19 @@ _rl_abort_internal () } int -rl_abort (count, key) - int count, key; +rl_abort (int count, int key) { return (_rl_abort_internal ()); } int -_rl_null_function (count, key) - int count, key; +_rl_null_function (int count, int key) { return 0; } int -rl_tty_status (count, key) - int count, key; +rl_tty_status (int count, int key) { #if defined (TIOCSTAT) ioctl (1, TIOCSTAT, (char *)0); @@ -146,8 +142,7 @@ rl_tty_status (count, key) /* Return a copy of the string between FROM and TO. FROM is inclusive, TO is not. */ char * -rl_copy_text (from, to) - int from, to; +rl_copy_text (int from, int to) { register int length; char *copy; @@ -166,8 +161,7 @@ rl_copy_text (from, to) /* Increase the size of RL_LINE_BUFFER until it has enough space to hold LEN characters. */ void -rl_extend_line_buffer (len) - int len; +rl_extend_line_buffer (int len) { while (len >= rl_line_buffer_len) { @@ -181,8 +175,7 @@ rl_extend_line_buffer (len) /* A function for simple tilde expansion. */ int -rl_tilde_expand (ignore, key) - int ignore, key; +rl_tilde_expand (int ignore, int key) { register int start, end; char *homedir, *temp; @@ -200,7 +193,7 @@ rl_tilde_expand (ignore, key) } else if (start >= 0 && rl_line_buffer[start] != '~') { - for (; !whitespace (rl_line_buffer[start]) && start >= 0; start--) + for (; start >= 0 && !whitespace (rl_line_buffer[start]); start--) ; start++; } @@ -324,8 +317,7 @@ _rl_errmsg (format, arg1, arg2) /* Determine if s2 occurs in s1. If so, return a pointer to the match in s1. The compare is case insensitive. */ char * -_rl_strindex (s1, s2) - register const char *s1, *s2; +_rl_strindex (const char *s1, const char *s2) { register int i, l, len; @@ -339,8 +331,7 @@ _rl_strindex (s1, s2) /* Find the first occurrence in STRING1 of any character from STRING2. Return a pointer to the character in STRING1. */ char * -_rl_strpbrk (string1, string2) - const char *string1, *string2; +_rl_strpbrk (const char *string1, const char *string2) { register const char *scan; #if defined (HANDLE_MULTIBYTE) @@ -374,10 +365,7 @@ _rl_strpbrk (string1, string2) /* Compare at most COUNT characters from string1 to string2. Case doesn't matter (strncasecmp). */ int -_rl_strnicmp (string1, string2, count) - const char *string1; - const char *string2; - int count; +_rl_strnicmp (const char *string1, const char *string2, int count) { register const char *s1; register const char *s2; @@ -404,9 +392,7 @@ _rl_strnicmp (string1, string2, count) /* strcmp (), but caseless (strcasecmp). */ int -_rl_stricmp (string1, string2) - const char *string1; - const char *string2; +_rl_stricmp (const char *string1, const char *string2) { register const char *s1; register const char *s2; @@ -431,8 +417,7 @@ _rl_stricmp (string1, string2) /* Stupid comparison routine for qsort () ing strings. */ int -_rl_qsort_string_compare (s1, s2) - char **s1, **s2; +_rl_qsort_string_compare (char **s1, char **s2) { #if defined (HAVE_STRCOLL) return (strcoll (*s1, *s2)); @@ -448,7 +433,7 @@ _rl_qsort_string_compare (s1, s2) } /* Function equivalents for the macros defined in chardefs.h. */ -#define FUNCTION_FOR_MACRO(f) int (f) (c) int c; { return f (c); } +#define FUNCTION_FOR_MACRO(f) int (f) (int c) { return f (c); } FUNCTION_FOR_MACRO (_rl_digit_p) FUNCTION_FOR_MACRO (_rl_digit_value) @@ -461,8 +446,7 @@ FUNCTION_FOR_MACRO (_rl_uppercase_p) /* A convenience function, to force memory deallocation to be performed by readline. DLLs on Windows apparently require this. */ void -rl_free (mem) - void *mem; +rl_free (void *mem) { if (mem) free (mem); @@ -472,8 +456,7 @@ rl_free (mem) all `public' readline header files. */ #undef _rl_savestring char * -_rl_savestring (s) - const char *s; +_rl_savestring (const char *s) { return (strcpy ((char *)xmalloc (1 + (int)strlen (s)), (s))); } @@ -512,7 +495,7 @@ _rl_trace (va_alist) } int -_rl_tropen () +_rl_tropen (void) { char fnbuf[128], *x; @@ -525,14 +508,14 @@ _rl_tropen () #else x = "/var/tmp"; #endif - sprintf (fnbuf, "%s/rltrace.%ld", x, (long)getpid()); + snprintf (fnbuf, sizeof (fnbuf), "%s/rltrace.%ld", x, (long)getpid()); unlink(fnbuf); _rl_tracefp = fopen (fnbuf, "w+"); return _rl_tracefp != 0; } int -_rl_trclose () +_rl_trclose (void) { int r; @@ -542,8 +525,7 @@ _rl_trclose () } void -_rl_settracefp (fp) - FILE *fp; +_rl_settracefp (FILE *fp) { _rl_tracefp = fp; } @@ -559,8 +541,7 @@ _rl_settracefp (fp) /* Report STRING to the audit system. */ void -_rl_audit_tty (string) - char *string; +_rl_audit_tty (char *string) { struct audit_message req; struct sockaddr_nl addr; diff --git a/lib/readline/vi_keymap.c b/lib/readline/vi_keymap.c index e5da2e0f..045258bd 100644 --- a/lib/readline/vi_keymap.c +++ b/lib/readline/vi_keymap.c @@ -1,6 +1,6 @@ /* vi_keymap.c -- the keymap for vi_mode in readline (). */ -/* Copyright (C) 1987-2016 Free Software Foundation, Inc. +/* Copyright (C) 1987-2017 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. diff --git a/lib/readline/vi_mode.c b/lib/readline/vi_mode.c index 56d2e72f..3cb7e8c9 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-2016 Free Software Foundation, Inc. +/* Copyright (C) 1987-2017 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,6 +63,8 @@ #define member(c, s) ((c) ? (char *)strchr ((s), (c)) != (char *)NULL : 0) #endif +/* This is global so other parts of the code can check whether the last + command was a text modification command. */ int _rl_vi_last_command = 'i'; /* default `.' puts you in insert mode */ _rl_vimotion_cxt *_rl_vimvcxt = 0; @@ -99,7 +101,7 @@ static int _rl_vi_last_search_mblen; #else static int _rl_vi_last_search_char; #endif -static int _rl_vi_last_replacement; +static char _rl_vi_last_replacement[MB_LEN_MAX+1]; /* reserve for trailing NULL */ static int _rl_vi_last_key_before_insert; @@ -146,7 +148,7 @@ static int vi_yank_dispatch PARAMS((_rl_vimotion_cxt *)); static int vidomove_dispatch PARAMS((_rl_vimotion_cxt *)); void -_rl_vi_initialize_line () +_rl_vi_initialize_line (void) { register int i, n; @@ -158,7 +160,7 @@ _rl_vi_initialize_line () } void -_rl_vi_reset_last () +_rl_vi_reset_last (void) { _rl_vi_last_command = 'i'; _rl_vi_last_repeat = 1; @@ -167,8 +169,7 @@ _rl_vi_reset_last () } void -_rl_vi_set_last (key, repeat, sign) - int key, repeat, sign; +_rl_vi_set_last (int key, int repeat, int sign) { _rl_vi_last_command = key; _rl_vi_last_repeat = repeat; @@ -178,8 +179,7 @@ _rl_vi_set_last (key, repeat, sign) /* A convenience function that calls _rl_vi_set_last to save the last command information and enters insertion mode. */ void -rl_vi_start_inserting (key, repeat, sign) - int key, repeat, sign; +rl_vi_start_inserting (int key, int repeat, int sign) { _rl_vi_set_last (key, repeat, sign); rl_vi_insertion_mode (1, key); @@ -187,22 +187,19 @@ rl_vi_start_inserting (key, repeat, sign) /* Is the command C a VI mode text modification command? */ int -_rl_vi_textmod_command (c) - int c; +_rl_vi_textmod_command (int c) { return (member (c, vi_textmod)); } int -_rl_vi_motion_command (c) - int c; +_rl_vi_motion_command (int c) { return (member (c, vi_motion)); } static void -_rl_vi_replace_insert (count) - int count; +_rl_vi_replace_insert (int count) { int nchars; @@ -217,8 +214,7 @@ _rl_vi_replace_insert (count) } static void -_rl_vi_stuff_insert (count) - int count; +_rl_vi_stuff_insert (int count) { rl_begin_undo_group (); while (count--) @@ -230,8 +226,7 @@ _rl_vi_stuff_insert (count) redo a text modification command. The default for _rl_vi_last_command puts you back into insert mode. */ int -rl_vi_redo (count, c) - int count, c; +rl_vi_redo (int count, int c) { int r; @@ -296,16 +291,14 @@ rl_vi_redo (count, c) /* A placeholder for further expansion. */ int -rl_vi_undo (count, key) - int count, key; +rl_vi_undo (int count, int key) { return (rl_undo_command (count, key)); } /* Yank the nth arg from the previous line into this line at point. */ int -rl_vi_yank_arg (count, key) - int count, key; +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. */ @@ -320,8 +313,7 @@ rl_vi_yank_arg (count, key) /* With an argument, move back that many history lines, else move to the beginning of history. */ int -rl_vi_fetch_history (count, c) - int count, c; +rl_vi_fetch_history (int count, int c) { int wanted; @@ -345,8 +337,7 @@ rl_vi_fetch_history (count, c) /* Search again for the last thing searched for. */ int -rl_vi_search_again (count, key) - int count, key; +rl_vi_search_again (int count, int key) { switch (key) { @@ -363,8 +354,7 @@ rl_vi_search_again (count, key) /* Do a vi style search. */ int -rl_vi_search (count, key) - int count, key; +rl_vi_search (int count, int key) { switch (key) { @@ -387,8 +377,7 @@ rl_vi_search (count, key) /* Completion, from vi's point of view. */ int -rl_vi_complete (ignore, key) - int ignore, key; +rl_vi_complete (int ignore, int key) { if ((rl_point < rl_end) && (!whitespace (rl_line_buffer[rl_point]))) { @@ -414,8 +403,7 @@ rl_vi_complete (ignore, key) /* Tilde expansion for vi mode. */ int -rl_vi_tilde_expand (ignore, key) - int ignore, key; +rl_vi_tilde_expand (int ignore, int key) { rl_tilde_expand (0, key); rl_vi_start_inserting (key, 1, rl_arg_sign); @@ -424,8 +412,7 @@ rl_vi_tilde_expand (ignore, key) /* Previous word in vi mode. */ int -rl_vi_prev_word (count, key) - int count, key; +rl_vi_prev_word (int count, int key) { if (count < 0) return (rl_vi_next_word (-count, key)); @@ -446,8 +433,7 @@ rl_vi_prev_word (count, key) /* Next word in vi mode. */ int -rl_vi_next_word (count, key) - int count, key; +rl_vi_next_word (int count, int key) { if (count < 0) return (rl_vi_prev_word (-count, key)); @@ -467,8 +453,7 @@ rl_vi_next_word (count, key) /* Move to the end of the ?next? word. */ int -rl_vi_end_word (count, key) - int count, key; +rl_vi_end_word (int count, int key) { if (count < 0) { @@ -485,8 +470,7 @@ rl_vi_end_word (count, key) /* Move forward a word the way that 'W' does. */ int -rl_vi_fWord (count, ignore) - int count, ignore; +rl_vi_fWord (int count, int ignore) { while (count-- && rl_point < (rl_end - 1)) { @@ -502,8 +486,7 @@ rl_vi_fWord (count, ignore) } int -rl_vi_bWord (count, ignore) - int count, ignore; +rl_vi_bWord (int count, int ignore) { while (count-- && rl_point > 0) { @@ -526,8 +509,7 @@ rl_vi_bWord (count, ignore) } int -rl_vi_eWord (count, ignore) - int count, ignore; +rl_vi_eWord (int count, int ignore) { while (count-- && rl_point < (rl_end - 1)) { @@ -557,8 +539,7 @@ rl_vi_eWord (count, ignore) } int -rl_vi_fword (count, ignore) - int count, ignore; +rl_vi_fword (int count, int ignore) { while (count-- && rl_point < (rl_end - 1)) { @@ -583,8 +564,7 @@ rl_vi_fword (count, ignore) } int -rl_vi_bword (count, ignore) - int count, ignore; +rl_vi_bword (int count, int ignore) { while (count-- && rl_point > 0) { @@ -594,7 +574,8 @@ rl_vi_bword (count, ignore) so we will go back to the start of the previous word. */ if (!whitespace (rl_line_buffer[rl_point]) && whitespace (rl_line_buffer[rl_point - 1])) - rl_point--; + if (--rl_point == 0) + break; /* If this character and the previous character are `opposite', move back so we don't get messed up by the rl_point++ down there in @@ -622,8 +603,7 @@ rl_vi_bword (count, ignore) } int -rl_vi_eword (count, ignore) - int count, ignore; +rl_vi_eword (int count, int ignore) { while (count-- && rl_point < rl_end - 1) { @@ -647,8 +627,7 @@ rl_vi_eword (count, ignore) } int -rl_vi_insert_beg (count, key) - int count, key; +rl_vi_insert_beg (int count, int key) { rl_beg_of_line (1, key); rl_vi_insert_mode (1, key); @@ -656,8 +635,7 @@ rl_vi_insert_beg (count, key) } static void -_rl_vi_append_forward (key) - int key; +_rl_vi_append_forward (int key) { int point; @@ -668,11 +646,7 @@ _rl_vi_append_forward (key) else { point = rl_point; -#if 0 - rl_forward_char (1, key); -#else rl_point = _rl_forward_char_internal (1); -#endif if (point == rl_point) rl_point = rl_end; } @@ -680,8 +654,7 @@ _rl_vi_append_forward (key) } int -rl_vi_append_mode (count, key) - int count, key; +rl_vi_append_mode (int count, int key) { _rl_vi_append_forward (key); rl_vi_start_inserting (key, 1, rl_arg_sign); @@ -689,8 +662,7 @@ rl_vi_append_mode (count, key) } int -rl_vi_append_eol (count, key) - int count, key; +rl_vi_append_eol (int count, int key) { rl_end_of_line (1, key); rl_vi_append_mode (1, key); @@ -699,8 +671,7 @@ rl_vi_append_eol (count, key) /* What to do in the case of C-d. */ int -rl_vi_eof_maybe (count, c) - int count, c; +rl_vi_eof_maybe (int count, int c) { return (rl_newline (1, '\n')); } @@ -710,8 +681,7 @@ rl_vi_eof_maybe (count, c) /* Switching from one mode to the other really just involves switching keymaps. */ int -rl_vi_insertion_mode (count, key) - int count, key; +rl_vi_insertion_mode (int count, int key) { _rl_keymap = vi_insertion_keymap; _rl_vi_last_key_before_insert = key; @@ -721,16 +691,14 @@ rl_vi_insertion_mode (count, key) } int -rl_vi_insert_mode (count, key) - int count, key; +rl_vi_insert_mode (int count, int key) { rl_vi_start_inserting (key, 1, rl_arg_sign); return (0); } static void -vi_save_insert_buffer (start, len) - int start, len; +vi_save_insert_buffer (int start, int len) { /* Same code as _rl_vi_save_insert below */ if (len >= vi_insert_buffer_size) @@ -743,7 +711,7 @@ vi_save_insert_buffer (start, len) } static void -_rl_vi_save_replace () +_rl_vi_save_replace (void) { int len, start, end; UNDO_LIST *up; @@ -766,8 +734,7 @@ _rl_vi_save_replace () } static void -_rl_vi_save_insert (up) - UNDO_LIST *up; +_rl_vi_save_insert (UNDO_LIST *up) { int len, start, end; @@ -786,7 +753,7 @@ _rl_vi_save_insert (up) } void -_rl_vi_done_inserting () +_rl_vi_done_inserting (void) { if (_rl_vi_doing_insert) { @@ -821,8 +788,7 @@ _rl_vi_done_inserting () } int -rl_vi_movement_mode (count, key) - int count, key; +rl_vi_movement_mode (int count, int key) { if (rl_point > 0) rl_backward_char (1, key); @@ -843,8 +809,7 @@ rl_vi_movement_mode (count, key) } int -rl_vi_arg_digit (count, c) - int count, c; +rl_vi_arg_digit (int count, int c) { if (c == '0' && rl_numeric_arg == 1 && !rl_explicit_arg) return (rl_beg_of_line (1, c)); @@ -855,8 +820,7 @@ rl_vi_arg_digit (count, c) /* Change the case of the next COUNT characters. */ #if defined (HANDLE_MULTIBYTE) static int -_rl_vi_change_mbchar_case (count) - int count; +_rl_vi_change_mbchar_case (int count) { wchar_t wc; char mb[MB_LEN_MAX+1]; @@ -909,8 +873,7 @@ _rl_vi_change_mbchar_case (count) #endif int -rl_vi_change_case (count, ignore) - int count, ignore; +rl_vi_change_case (int count, int ignore) { int c, p; @@ -956,8 +919,7 @@ rl_vi_change_case (count, ignore) } int -rl_vi_put (count, key) - int count, key; +rl_vi_put (int count, int key) { if (!_rl_uppercase_p (key) && (rl_point + 1 <= rl_end)) rl_point = _rl_find_next_mbchar (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO); @@ -969,8 +931,9 @@ rl_vi_put (count, key) return (0); } +/* Move the cursor back one character. */ static void -_rl_vi_backup () +_rl_vi_backup (void) { if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO); @@ -978,8 +941,9 @@ _rl_vi_backup () rl_point--; } +/* Move the cursor back one character if you're at the end of the line */ int -rl_vi_check () +rl_vi_check (void) { if (rl_point && rl_point == rl_end) { @@ -991,9 +955,9 @@ rl_vi_check () return (0); } +/* Move to the character position specified by COUNT */ int -rl_vi_column (count, key) - int count, key; +rl_vi_column (int count, int key) { if (count > rl_end) rl_end_of_line (1, key); @@ -1006,8 +970,7 @@ rl_vi_column (count, key) argument should be aborted, 0 if we should not read any more chars, and 1 if we should continue to read chars. */ static int -_rl_vi_arg_dispatch (c) - int c; +_rl_vi_arg_dispatch (int c) { int key; @@ -1041,7 +1004,7 @@ _rl_vi_arg_dispatch (c) Don't recognize minus sign? Should this do rl_save_prompt/rl_restore_prompt? */ static int -rl_digit_loop1 () +rl_digit_loop1 (void) { int c, r; @@ -1061,10 +1024,12 @@ rl_digit_loop1 () return (0); } +/* This set of functions is basically to handle the commands that take a + motion argument while in callback mode: read the command, read the motion + command modifier, find the extent of the text to affect, and dispatch the + command for execution. */ static void -_rl_mvcxt_init (m, op, key) - _rl_vimotion_cxt *m; - int op, key; +_rl_mvcxt_init (_rl_vimotion_cxt *m, int op, int key) { m->op = op; m->state = m->flags = 0; @@ -1077,8 +1042,7 @@ _rl_mvcxt_init (m, op, key) } static _rl_vimotion_cxt * -_rl_mvcxt_alloc (op, key) - int op, key; +_rl_mvcxt_alloc (int op, int key) { _rl_vimotion_cxt *m; @@ -1088,15 +1052,13 @@ _rl_mvcxt_alloc (op, key) } static void -_rl_mvcxt_dispose (m) - _rl_vimotion_cxt *m; +_rl_mvcxt_dispose (_rl_vimotion_cxt *m) { xfree (m); } static int -rl_domove_motion_callback (m) - _rl_vimotion_cxt *m; +rl_domove_motion_callback (_rl_vimotion_cxt *m) { int c; @@ -1129,9 +1091,7 @@ rl_domove_motion_callback (m) } int -_rl_vi_domove_motion_cleanup (c, m) - int c; - _rl_vimotion_cxt *m; +_rl_vi_domove_motion_cleanup (int c, _rl_vimotion_cxt *m) { int r; @@ -1193,8 +1153,7 @@ _rl_vi_domove_motion_cleanup (c, m) #define RL_VIMOVENUMARG() (RL_ISSTATE (RL_STATE_VIMOTION) && RL_ISSTATE (RL_STATE_NUMERICARG)) static int -rl_domove_read_callback (m) - _rl_vimotion_cxt *m; +rl_domove_read_callback (_rl_vimotion_cxt *m) { int c, save; @@ -1260,8 +1219,7 @@ rl_domove_read_callback (m) } static int -rl_vi_domove_getchar (m) - _rl_vimotion_cxt *m; +rl_vi_domove_getchar (_rl_vimotion_cxt *m) { int c; @@ -1274,8 +1232,7 @@ rl_vi_domove_getchar (m) #if defined (READLINE_CALLBACKS) int -_rl_vi_domove_callback (m) - _rl_vimotion_cxt *m; +_rl_vi_domove_callback (_rl_vimotion_cxt *m) { int c, r; @@ -1288,10 +1245,9 @@ _rl_vi_domove_callback (m) } #endif -/* This code path taken when not in callback mode. */ +/* This code path is taken when not in callback mode. */ int -rl_vi_domove (x, ignore) - int x, *ignore; +rl_vi_domove (int x, int *ignore) { int r; _rl_vimotion_cxt *m; @@ -1309,8 +1265,7 @@ rl_vi_domove (x, ignore) } static int -vi_delete_dispatch (m) - _rl_vimotion_cxt *m; +vi_delete_dispatch (_rl_vimotion_cxt *m) { /* These are the motion commands that do not require adjusting the mark. */ @@ -1323,8 +1278,7 @@ vi_delete_dispatch (m) } int -rl_vi_delete_to (count, key) - int count, key; +rl_vi_delete_to (int count, int key) { int c, r; @@ -1373,8 +1327,7 @@ rl_vi_delete_to (count, key) } static int -vi_change_dispatch (m) - _rl_vimotion_cxt *m; +vi_change_dispatch (_rl_vimotion_cxt *m) { /* These are the motion commands that do not require adjusting the mark. c[wW] are handled by special-case code in rl_vi_domove(), @@ -1413,8 +1366,7 @@ vi_change_dispatch (m) } int -rl_vi_change_to (count, key) - int count, key; +rl_vi_change_to (int count, int key) { int c, r; @@ -1463,8 +1415,7 @@ rl_vi_change_to (count, key) } static int -vi_yank_dispatch (m) - _rl_vimotion_cxt *m; +vi_yank_dispatch (_rl_vimotion_cxt *m) { /* These are the motion commands that do not require adjusting the mark. */ @@ -1482,8 +1433,7 @@ vi_yank_dispatch (m) } int -rl_vi_yank_to (count, key) - int count, key; +rl_vi_yank_to (int count, int key) { int c, r; @@ -1532,8 +1482,7 @@ rl_vi_yank_to (count, key) } static int -vidomove_dispatch (m) - _rl_vimotion_cxt *m; +vidomove_dispatch (_rl_vimotion_cxt *m) { int r; @@ -1559,8 +1508,7 @@ vidomove_dispatch (m) } int -rl_vi_rubout (count, key) - int count, key; +rl_vi_rubout (int count, int key) { int opoint; @@ -1590,8 +1538,7 @@ rl_vi_rubout (count, key) } int -rl_vi_delete (count, key) - int count, key; +rl_vi_delete (int count, int key) { int end; @@ -1626,8 +1573,7 @@ rl_vi_delete (count, key) #define vi_unix_word_boundary(c) (whitespace(c) || ispunct(c)) int -rl_vi_unix_word_rubout (count, key) - int count, key; +rl_vi_unix_word_rubout (int count, int key) { int orig_point; @@ -1677,8 +1623,7 @@ rl_vi_unix_word_rubout (count, key) int -rl_vi_back_to_indent (count, key) - int count, key; +rl_vi_back_to_indent (int count, int key) { rl_beg_of_line (1, key); while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point])) @@ -1687,8 +1632,7 @@ rl_vi_back_to_indent (count, key) } int -rl_vi_first_print (count, key) - int count, key; +rl_vi_first_print (int count, int key) { return (rl_vi_back_to_indent (1, key)); } @@ -1697,8 +1641,7 @@ static int _rl_cs_dir, _rl_cs_orig_dir; #if defined (READLINE_CALLBACKS) static int -_rl_vi_callback_char_search (data) - _rl_callback_generic_arg *data; +_rl_vi_callback_char_search (_rl_callback_generic_arg *data) { int c; #if defined (HANDLE_MULTIBYTE) @@ -1732,8 +1675,7 @@ _rl_vi_callback_char_search (data) #endif int -rl_vi_char_search (count, key) - int count, key; +rl_vi_char_search (int count, int key) { int c; #if defined (HANDLE_MULTIBYTE) @@ -1826,8 +1768,7 @@ rl_vi_char_search (count, key) /* Match brackets */ int -rl_vi_match (ignore, key) - int ignore, key; +rl_vi_match (int ignore, int key) { int count = 1, brack, pos, tmp, pre; @@ -1916,8 +1857,7 @@ rl_vi_match (ignore, key) } int -rl_vi_bracktype (c) - int c; +rl_vi_bracktype (int c) { switch (c) { @@ -1932,9 +1872,7 @@ rl_vi_bracktype (c) } static int -_rl_vi_change_char (count, c, mb) - int count, c; - char *mb; +_rl_vi_change_char (int count, int c, char *mb) { int p; @@ -1947,7 +1885,7 @@ _rl_vi_change_char (count, c, mb) p = rl_point; rl_vi_delete (1, c); if (rl_point < p) /* Did we retreat at EOL? */ - rl_point++; + _rl_vi_append_forward (c); #if defined (HANDLE_MULTIBYTE) if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) rl_insert_text (mb); @@ -1965,9 +1903,7 @@ _rl_vi_change_char (count, c, mb) } static int -_rl_vi_callback_getchar (mb, mlen) - char *mb; - int mlen; +_rl_vi_callback_getchar (char *mb, int mlen) { int c; @@ -1988,13 +1924,18 @@ _rl_vi_callback_getchar (mb, mlen) #if defined (READLINE_CALLBACKS) static int -_rl_vi_callback_change_char (data) - _rl_callback_generic_arg *data; +_rl_vi_callback_change_char (_rl_callback_generic_arg *data) { int c; - char mb[MB_LEN_MAX]; + char mb[MB_LEN_MAX+1]; - _rl_vi_last_replacement = c = _rl_vi_callback_getchar (mb, MB_LEN_MAX); + 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; +#endif + _rl_vi_last_replacement[MB_LEN_MAX] = '\0'; /* XXX */ if (c < 0) return -1; @@ -2007,17 +1948,16 @@ _rl_vi_callback_change_char (data) #endif int -rl_vi_change_char (count, key) - int count, key; +rl_vi_change_char (int count, int key) { int c; - char mb[MB_LEN_MAX]; + char mb[MB_LEN_MAX+1]; if (_rl_vi_redoing) { - c = _rl_vi_last_replacement; - mb[0] = c; - mb[1] = '\0'; + strncpy (mb, _rl_vi_last_replacement, MB_LEN_MAX); + c = (unsigned char)_rl_vi_last_replacement[0]; /* XXX */ + mb[MB_LEN_MAX] = '\0'; } #if defined (READLINE_CALLBACKS) else if (RL_ISSTATE (RL_STATE_CALLBACK)) @@ -2028,7 +1968,15 @@ rl_vi_change_char (count, key) } #endif else - _rl_vi_last_replacement = c = _rl_vi_callback_getchar (mb, MB_LEN_MAX); + { + 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; +#endif + _rl_vi_last_replacement[MB_LEN_MAX] = '\0'; /* just in case */ + } if (c < 0) return -1; @@ -2037,8 +1985,7 @@ rl_vi_change_char (count, key) } int -rl_vi_subst (count, key) - int count, key; +rl_vi_subst (int count, int key) { /* If we are redoing, rl_vi_change_to will stuff the last motion char */ if (_rl_vi_redoing == 0) @@ -2048,8 +1995,7 @@ rl_vi_subst (count, key) } int -rl_vi_overstrike (count, key) - int count, key; +rl_vi_overstrike (int count, int key) { if (_rl_vi_doing_insert == 0) { @@ -2067,8 +2013,7 @@ rl_vi_overstrike (count, key) } int -rl_vi_overstrike_delete (count, key) - int count, key; +rl_vi_overstrike_delete (int count, int key) { int i, s; @@ -2098,8 +2043,7 @@ rl_vi_overstrike_delete (count, key) } int -rl_vi_replace (count, key) - int count, key; +rl_vi_replace (int count, int key) { int i; @@ -2130,6 +2074,9 @@ rl_vi_replace (count, key) vi_insertion_keymap[CTRL ('H')].function == rl_rubout) vi_replace_map[CTRL ('H')].function = rl_vi_overstrike_delete; + /* Make sure this is the value we need. */ + vi_replace_map[ANYOTHERKEY].type = ISFUNC; + vi_replace_map[ANYOTHERKEY].function = (rl_command_func_t *)NULL; } rl_vi_start_inserting (key, 1, rl_arg_sign); @@ -2145,7 +2092,7 @@ rl_vi_replace (count, key) the previous character. A space matches everything. Word delimiters are space and ;. */ int -rl_vi_possible_completions() +rl_vi_possible_completions (void) { int save_pos = rl_point; @@ -2170,7 +2117,7 @@ rl_vi_possible_completions() /* Functions to save and restore marks. */ static int -_rl_vi_set_mark () +_rl_vi_set_mark (void) { int ch; @@ -2190,8 +2137,7 @@ _rl_vi_set_mark () #if defined (READLINE_CALLBACKS) static int -_rl_vi_callback_set_mark (data) - _rl_callback_generic_arg *data; +_rl_vi_callback_set_mark (_rl_callback_generic_arg *data) { _rl_callback_func = 0; _rl_want_redisplay = 1; @@ -2201,8 +2147,7 @@ _rl_vi_callback_set_mark (data) #endif int -rl_vi_set_mark (count, key) - int count, key; +rl_vi_set_mark (int count, int key) { #if defined (READLINE_CALLBACKS) if (RL_ISSTATE (RL_STATE_CALLBACK)) @@ -2217,7 +2162,7 @@ rl_vi_set_mark (count, key) } static int -_rl_vi_goto_mark () +_rl_vi_goto_mark (void) { int ch; @@ -2248,8 +2193,7 @@ _rl_vi_goto_mark () #if defined (READLINE_CALLBACKS) static int -_rl_vi_callback_goto_mark (data) - _rl_callback_generic_arg *data; +_rl_vi_callback_goto_mark (_rl_callback_generic_arg *data) { _rl_callback_func = 0; _rl_want_redisplay = 1; @@ -2259,8 +2203,7 @@ _rl_vi_callback_goto_mark (data) #endif int -rl_vi_goto_mark (count, key) - int count, key; +rl_vi_goto_mark (int count, int key) { #if defined (READLINE_CALLBACKS) if (RL_ISSTATE (RL_STATE_CALLBACK)) diff --git a/lib/readline/xfree.c b/lib/readline/xfree.c index 37a81e6c..c199b29b 100644 --- a/lib/readline/xfree.c +++ b/lib/readline/xfree.c @@ -1,6 +1,6 @@ /* xfree.c -- safe version of free that ignores attempts to free NUL */ -/* Copyright (C) 1991-2010 Free Software Foundation, Inc. +/* Copyright (C) 1991-2010,2017 Free Software Foundation, Inc. This file is part of the GNU Readline Library (Readline), a library for reading lines of text with interactive input and history editing. @@ -42,8 +42,7 @@ /* Use this as the function to call when adding unwind protects so we don't need to know what free() returns. */ void -xfree (string) - PTR_T string; +xfree (PTR_T string) { if (string) free (string); diff --git a/lib/readline/xmalloc.c b/lib/readline/xmalloc.c index c77d7634..5d01d75e 100644 --- a/lib/readline/xmalloc.c +++ b/lib/readline/xmalloc.c @@ -1,6 +1,6 @@ /* xmalloc.c -- safe versions of malloc and realloc */ -/* Copyright (C) 1991-2009 Free Software Foundation, Inc. +/* Copyright (C) 1991-2017 Free Software Foundation, Inc. This file is part of the GNU Readline Library (Readline), a library for reading lines of text with interactive input and history editing. @@ -42,8 +42,7 @@ /* **************************************************************** */ static void -memory_error_and_abort (fname) - char *fname; +memory_error_and_abort (char *fname) { fprintf (stderr, "%s: out of virtual memory\n", fname); exit (2); @@ -53,8 +52,7 @@ memory_error_and_abort (fname) to hold BYTES number of bytes. If the memory cannot be allocated, print an error message and abort. */ PTR_T -xmalloc (bytes) - size_t bytes; +xmalloc (size_t bytes) { PTR_T temp; @@ -65,9 +63,7 @@ xmalloc (bytes) } PTR_T -xrealloc (pointer, bytes) - PTR_T pointer; - size_t bytes; +xrealloc (PTR_T pointer, size_t bytes) { PTR_T temp; diff --git a/lib/sh/Makefile.in b/lib/sh/Makefile.in index 2ca921b3..b1a086d6 100644 --- a/lib/sh/Makefile.in +++ b/lib/sh/Makefile.in @@ -67,8 +67,8 @@ LOCAL_DEFS = @LOCAL_DEFS@ INCLUDES = -I. -I../.. -I$(topdir) -I$(topdir)/lib -I$(BASHINCDIR) -I$(srcdir) $(INTL_INC) -CCFLAGS = ${PROFILE_FLAGS} ${INCLUDES} $(DEFS) $(LOCAL_DEFS) $(LOCAL_CFLAGS) \ - $(CFLAGS) $(CPPFLAGS) +CCFLAGS = ${ADDON_CFLAGS} ${PROFILE_FLAGS} ${INCLUDES} $(DEFS) $(LOCAL_DEFS) \ + $(LOCAL_CFLAGS) $(CFLAGS) $(CPPFLAGS) GCC_LINT_FLAGS = -Wall -Wshadow -Wpointer-arith -Wcast-qual \ -Wcast-align -Wstrict-prototypes -Wconversion \ diff --git a/lib/sh/casemod.c b/lib/sh/casemod.c index f68303bc..7cdd4178 100644 --- a/lib/sh/casemod.c +++ b/lib/sh/casemod.c @@ -229,7 +229,10 @@ singlebyte: else { m = mbrtowc (&wc, string + start, end - start, &state); - if (MB_INVALIDCH (m) || m == 1) + /* Have to go through wide case conversion even for single-byte + chars, to accommodate single-byte characters where the + corresponding upper or lower case equivalent is multibyte. */ + if (MB_INVALIDCH (m)) { wc = (unsigned char)string[start]; goto singlebyte; diff --git a/lib/sh/clock.c b/lib/sh/clock.c index 84cdbc54..c6c52bf8 100644 --- a/lib/sh/clock.c +++ b/lib/sh/clock.c @@ -32,7 +32,13 @@ #include <stdio.h> #include <stdc.h> -extern long get_clk_tck __P((void)); +#include <bashintl.h> + +#ifndef locale_decpoint +extern int locale_decpoint PARAMS((void)); +#endif + +extern long get_clk_tck PARAMS((void)); void clock_t_to_secs (t, sp, sfp) @@ -76,6 +82,6 @@ print_clock_t (fp, t) minutes = timestamp / 60; seconds = timestamp % 60; - fprintf (fp, "%ldm%d.%03ds", minutes, seconds, seconds_fraction); + fprintf (fp, "%ldm%d%c%03ds", minutes, seconds, locale_decpoint(), seconds_fraction); } #endif /* HAVE_TIMES */ diff --git a/lib/sh/eaccess.c b/lib/sh/eaccess.c index 8fd8a43e..3d8ae4e8 100644 --- a/lib/sh/eaccess.c +++ b/lib/sh/eaccess.c @@ -91,7 +91,9 @@ sh_stat (path, finfo) } if (path[0] == '/' && path[1] == 'd' && strncmp (path, "/dev/fd/", 8) == 0) { -#if !defined (HAVE_DEV_FD) + /* If stating /dev/fd/n doesn't produce the same results as fstat of + FD N, then define DEV_FD_STAT_BROKEN */ +#if !defined (HAVE_DEV_FD) || defined (DEV_FD_STAT_BROKEN) intmax_t fd; int r; diff --git a/lib/sh/mbschr.c b/lib/sh/mbschr.c index 7730e46e..fdce6d5a 100644 --- a/lib/sh/mbschr.c +++ b/lib/sh/mbschr.c @@ -28,9 +28,18 @@ #include "shmbutil.h" extern int locale_mb_cur_max; +extern int locale_utf8locale; #undef mbschr +static inline char * +utf8_mbschr (s, c) + const char *s; + int c; +{ + return strchr (s, c); /* for now */ +} + /* In some locales, the non-first byte of some multibyte characters have the same value as some ascii character. Faced with these strings, a legacy strchr() might return the wrong value. */ @@ -49,6 +58,9 @@ mbschr (s, c) mbstate_t state; size_t strlength, mblength; + if (locale_utf8locale && c < 0x80) + return (utf8_mbschr (s, c)); /* XXX */ + /* The locale encodings with said weird property are BIG5, BIG5-HKSCS, GBK, GB18030, SHIFT_JIS, and JOHAB. They exhibit the problem only when c >= 0x30. We can therefore use the faster bytewise search if diff --git a/lib/sh/shmbchar.c b/lib/sh/shmbchar.c index 7f14208e..80858ebf 100644 --- a/lib/sh/shmbchar.c +++ b/lib/sh/shmbchar.c @@ -20,9 +20,15 @@ #include <stdlib.h> #include <limits.h> +#include <errno.h> + #include <shmbutil.h> #include <shmbchar.h> +#ifndef errno +extern int errno; +#endif + #if IS_BASIC_ASCII /* Bit table of characters in the ISO C "basic character set". */ @@ -37,6 +43,106 @@ const unsigned int is_basic_table [UCHAR_MAX / 32 + 1] = #endif /* IS_BASIC_ASCII */ +extern int locale_utf8locale; + +/* We can optimize this if we know the locale is UTF-8, but needs to handle + malformed byte sequences. */ +static inline size_t +utf8_mbstrlen(s) + const char *s; +{ + size_t num = 0; + register unsigned char c; + + while ((c = *s++)) + /* bytes 0xc0 through 0xff are first byte of multi-byte sequence */ + if ((c & 0xc0) != 0x80) /* skip continuation bytes */ + ++num; + return (num); +} + +/* Adapted from GNU libutf8 */ +static inline int +utf8_mblen (s, n) + const char *s; + int n; +{ + unsigned char c; + + if (s == 0) + return 0; + else if (n == 0) + return -1; + + c = (unsigned char) *s; + if (c < 0x80) + return (c != 0); + else if (c < 0xc0) + goto return_error; + else + { + const char *start = s; + size_t count; + int check_unsafe; + + if (c < 0xe0) + { + count = 1; + if (c < 0xc2) + goto return_error; + check_unsafe = 0; + } + else if (c < 0xf0) + { + count = 2; + check_unsafe = (c == 0xe0); + } +#if SIZEOF_WCHAR_T == 4 + else if (c < 0xf8) + { + count = 3; + check_unsafe = (c == 0xe0); + } + else if (c < 0xfc) + { + count = 4; + check_unsafe = (c == 0xf8); + } + else if (c < 0xfe) + { + count = 5; + check_unsafe = (c == 0xfc); + } +#endif + else + goto return_error; + if (n <= count) + return -1; + s++; + c = (unsigned char) *s++ ^ 0x80; + if (c >= 0x40) + goto return_error; + if (--count > 0) + { + if (check_unsafe && ((c >> (6 - count)) == 0)) + goto return_error; + do + { + c = (unsigned char) *s++ ^ 0x80; + if (c >= 0x40) + goto return_error; + } + while (--count > 0); + } + return s - start; + } +return_error: + errno = EILSEQ; + return -1; +} + +/* Count the number of characters in S, counting multi-byte characters as a + single character. */ size_t mbstrlen (s) const char *s; @@ -64,7 +170,21 @@ mbstrlen (s) return nc; } +static inline char * +utf8_mbsmbchar (str) + const char *str; +{ + register char *s; + + for (s = (char *)str; *s; s++) + if ((*s & 0xc0) == 0x80) + return s; + return (0); +} + /* Return pointer to first multibyte char in S, or NULL if none. */ +/* XXX - if we know that the locale is UTF-8, we can just check whether or + not any byte has the eighth bit turned on */ char * mbsmbchar (s) const char *s; @@ -74,13 +194,19 @@ mbsmbchar (s) mbstate_t mbs = { 0 }; int mb_cur_max; + if (locale_utf8locale) + return (utf8_mbsmbchar (s)); /* XXX */ + mb_cur_max = MB_CUR_MAX; for (t = (char *)s; *t; t++) { if (is_basic (*t)) continue; - clen = mbrlen (t, mb_cur_max, &mbs); + if (locale_utf8locale) /* not used if above code active */ + clen = utf8_mblen (t, mb_cur_max); + else + clen = mbrlen (t, mb_cur_max, &mbs); if (clen == 0) return 0; @@ -93,6 +219,22 @@ mbsmbchar (s) return 0; } +static inline int +utf_mbsnlen(src, srclen, maxlen) + const char *src; + size_t srclen; + int maxlen; +{ + register int sind, count; + + for (sind = count = 0; src[sind] && sind <= maxlen; sind++) + { + if ((src[sind] & 0xc0) != 0x80) + count++; + } + return (count); +} + int sh_mbsnlen(src, srclen, maxlen) const char *src; diff --git a/lib/sh/shquote.c b/lib/sh/shquote.c index ecec5971..97e2bc53 100644 --- a/lib/sh/shquote.c +++ b/lib/sh/shquote.c @@ -228,7 +228,8 @@ sh_un_double_quote (string) going through the shell parser, which will protect the internal quoting characters. TABLE, if set, points to a map of the ascii code set with char needing to be backslash-quoted if table[char]==1. FLAGS, - if 1, causes tildes to be quoted as well. */ + if 1, causes tildes to be quoted as well. If FLAGS&2, backslash-quote + other shell blank characters. */ char * sh_backslash_quote (string, table, flags) @@ -273,6 +274,8 @@ sh_backslash_quote (string, table, flags) /* Tildes are special at the start of a word or after a `:' or `=' (technically unquoted, but it doesn't make a difference in practice) */ *r++ = '\\'; + else if ((flags&2) && shellblank((unsigned char)c)) + *r++ = '\\'; *r++ = c; } diff --git a/lib/sh/strtrans.c b/lib/sh/strtrans.c index 79831476..48f255f5 100644 --- a/lib/sh/strtrans.c +++ b/lib/sh/strtrans.c @@ -230,8 +230,6 @@ ansic_quote (str, flags, rlen) *r++ = '$'; *r++ = '\''; - s = str; - for (s = str; c = *s; s++) { b = l = 1; /* 1 == add backslash; 0 == no backslash */ @@ -305,11 +303,9 @@ ansic_wshouldquote (string) { const wchar_t *wcs; wchar_t wcc; - wchar_t *wcstr = NULL; size_t slen; - slen = mbstowcs (wcstr, string, 0); if (slen == (size_t)-1) diff --git a/lib/sh/timeval.c b/lib/sh/timeval.c index 7bd9df8f..c4b61dc8 100644 --- a/lib/sh/timeval.c +++ b/lib/sh/timeval.c @@ -25,6 +25,13 @@ #include <sys/types.h> #include <posixtime.h> +#include <bashintl.h> +#include <stdc.h> + +#ifndef locale_decpoint +extern int locale_decpoint PARAMS((void)); +#endif + #include <stdio.h> struct timeval * @@ -140,6 +147,6 @@ print_timeval (fp, tvp) minutes = timestamp / 60; seconds = timestamp % 60; - fprintf (fp, "%ldm%d.%03ds", minutes, seconds, seconds_fraction); + fprintf (fp, "%ldm%d%c%03ds", minutes, seconds, locale_decpoint (), seconds_fraction); } #endif /* HAVE_TIMEVAL */ diff --git a/lib/sh/ufuncs.c b/lib/sh/ufuncs.c index fcd4c044..ad9284cc 100644 --- a/lib/sh/ufuncs.c +++ b/lib/sh/ufuncs.c @@ -37,8 +37,16 @@ #include <unistd.h> #endif +#include <errno.h> +#if !defined (errno) +extern int errno; +#endif /* !errno */ + #if defined (HAVE_SELECT) # include "posixselect.h" +# include "quit.h" +# include "trap.h" +# include "stat-time.h" #endif /* A version of `alarm' using setitimer if it's available. */ @@ -84,17 +92,50 @@ falarm (secs, usecs) /* A version of sleep using fractional seconds and select. I'd like to use `usleep', but it's already taken */ -#if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) +#if defined (HAVE_TIMEVAL) && (defined (HAVE_SELECT) || defined (HAVE_PSELECT)) int fsleep(sec, usec) unsigned int sec, usec; { + int e, r; + sigset_t blocked_sigs, prevmask; +#if defined (HAVE_PSELECT) + struct timespec ts; +#else struct timeval tv; +#endif + sigemptyset (&blocked_sigs); +# if defined (SIGCHLD) + sigaddset (&blocked_sigs, SIGCHLD); +# endif + +#if defined (HAVE_PSELECT) + ts.tv_sec = sec; + ts.tv_nsec = usec * 1000; +#else + sigemptyset (&prevmask); tv.tv_sec = sec; tv.tv_usec = usec; +#endif /* !HAVE_PSELECT */ + + do + { +#if defined (HAVE_PSELECT) + r = pselect(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &ts, &blocked_sigs); +#else + sigprocmask (SIG_SETMASK, &blocked_sigs, &prevmask); + r = select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv); + sigprocmask (SIG_SETMASK, &prevmask, NULL); +#endif + e = errno; + if (r < 0 && errno == EINTR) + QUIT; /* just signals, no traps */ + errno = e; + } + while (r < 0 && errno == EINTR); - return select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv); + return r; } #else /* !HAVE_TIMEVAL || !HAVE_SELECT */ int diff --git a/lib/sh/unicode.c b/lib/sh/unicode.c index b58eaefd..fe13c4a0 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-2015 Free Software Foundation, Inc. +/* Copyright (C) 2010-2016 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne Again SHell. @@ -55,6 +55,8 @@ extern const char *locale_charset __P((void)); extern char *get_locale_var __P((char *)); #endif +extern int locale_utf8locale; + static int u32init = 0; static int utf8locale = 0; #if defined (HAVE_ICONV) @@ -219,12 +221,12 @@ u32toutf16 (c, s) int l; l = 0; - if (c < 0x0d800) + if (c < 0x0d800 || (c >= 0x0e000 && c <= 0x0ffff)) { s[0] = (unsigned short) (c & 0xFFFF); l = 1; } - else if (c >= 0x0e000 && c <= 0x010ffff) + else if (c >= 0x10000 && c <= 0x010ffff) { c -= 0x010000; s[0] = (unsigned short)((c >> 10) + 0xd800); @@ -265,28 +267,21 @@ u32cconv (c, s) return n; #endif -#if HAVE_NL_LANGINFO - codeset = nl_langinfo (CODESET); - if (STREQ (codeset, "UTF-8")) - { - n = u32toutf8 (c, s); - return n; - } -#endif - #if HAVE_ICONV /* this is mostly from coreutils-8.5/lib/unicodeio.c */ if (u32init == 0) { -# if HAVE_LOCALE_CHARSET - charset = locale_charset (); /* XXX - fix later */ -# else - charset = stub_charset (); -# endif - if (STREQ (charset, "UTF-8")) - utf8locale = 1; - else + utf8locale = locale_utf8locale; + localconv = (iconv_t)-1; + if (utf8locale == 0) { +#if HAVE_LOCALE_CHARSET + charset = locale_charset (); +#elif HAVE_NL_LANGINFO + charset = nl_langinfo (CODESET); +#else + charset = stub_charset (); +#endif localconv = iconv_open (charset, "UTF-8"); if (localconv == (iconv_t)-1) /* We assume ASCII when presented with an unknown encoding. */ @@ -295,6 +290,8 @@ u32cconv (c, s) u32init = 1; } + /* NL_LANGINFO and locale_charset used when setting locale_utf8locale */ + /* If we have a UTF-8 locale, convert to UTF-8 and return converted value. */ n = u32toutf8 (c, s); if (utf8locale) @@ -315,12 +312,8 @@ u32cconv (c, s) if (iconv (localconv, (ICONV_CONST char **)&iptr, &sn, &optr, &obytesleft) == (size_t)-1) { -#if 1 /* You get ISO C99 escape sequences if iconv fails */ n = u32tocesc (c, s); -#else - /* You get UTF-8 if iconv fails */ -#endif return n; } @@ -332,7 +325,10 @@ u32cconv (c, s) return (optr - obuf); #endif /* HAVE_ICONV */ - n = u32tocesc (c, s); /* fallback is ISO C99 escape sequences */ + if (locale_utf8locale) + n = u32toutf8 (c, s); + else + n = u32tocesc (c, s); /* fallback is ISO C99 escape sequences */ return n; } #else diff --git a/lib/sh/zread.c b/lib/sh/zread.c index 496f20b8..8b7ecedf 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-2002 Free Software Foundation, Inc. +/* Copyright (C) 1999-2017 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne Again SHell. @@ -53,6 +53,7 @@ zread (fd, buf, len) { ssize_t r; + 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 */ @@ -103,6 +104,7 @@ zreadintr (fd, buf, len) char *buf; size_t len; { + check_signals (); return (read (fd, buf, len)); } diff --git a/lib/tilde/Makefile.in b/lib/tilde/Makefile.in index 7ca3b789..c21d3897 100644 --- a/lib/tilde/Makefile.in +++ b/lib/tilde/Makefile.in @@ -52,7 +52,7 @@ BASHINCDIR = ${topdir}/include INCLUDES = -I. -I../.. -I$(topdir) -I${BASHINCDIR} -I$(topdir)/lib -CCFLAGS = $(PROFILE_FLAGS) $(DEFS) $(LOCAL_DEFS) $(CPPFLAGS) \ +CCFLAGS = ${ASAN_CFLAGS} $(PROFILE_FLAGS) $(DEFS) $(LOCAL_DEFS) $(CPPFLAGS) \ ${INCLUDES} $(LOCAL_CFLAGS) $(CFLAGS) .c.o: diff --git a/lib/tilde/shell.c b/lib/tilde/shell.c index fafb8619..9805a924 100644 --- a/lib/tilde/shell.c +++ b/lib/tilde/shell.c @@ -1,7 +1,7 @@ /* shell.c -- tilde utility functions that are normally provided by bash when readline is linked as part of the shell. */ -/* Copyright (C) 1998-2009 Free Software Foundation, Inc. +/* Copyright (C) 1998-2017 Free Software Foundation, Inc. This file is part of the GNU Tilde Library. @@ -49,8 +49,7 @@ extern struct passwd *getpwuid (); #endif /* !HAVE_GETPW_DECLS */ char * -get_env_value (varname) - char *varname; +get_env_value (char *varname) { return ((char *)getenv (varname)); } @@ -58,7 +57,7 @@ get_env_value (varname) /* If we're not using $HOME, assume that the passwd file information won't change while this shell instance is running. */ char * -get_home_dir () +get_home_dir (void) { static char *home_dir = (char *)NULL; struct passwd *entry; diff --git a/lib/tilde/tilde.c b/lib/tilde/tilde.c index 95bc4215..9d0f2961 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-2009 Free Software Foundation, Inc. +/* Copyright (C) 1988-2017 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. @@ -125,9 +125,7 @@ static char *glue_prefix_and_suffix PARAMS((char *, const char *, int)); the tilde which starts the expansion. Place the length of the text which identified this tilde starter in LEN, excluding the tilde itself. */ static int -tilde_find_prefix (string, len) - const char *string; - int *len; +tilde_find_prefix (const char *string, int *len) { register int i, j, string_len; register char **prefixes; @@ -160,8 +158,7 @@ tilde_find_prefix (string, len) /* Find the end of a tilde expansion in STRING, and return the index of the character which ends the tilde definition. */ static int -tilde_find_suffix (string) - const char *string; +tilde_find_suffix (const char *string) { register int i, j, string_len; register char **suffixes; @@ -189,8 +186,7 @@ tilde_find_suffix (string) /* Return a new string which is the result of tilde expanding STRING. */ char * -tilde_expand (string) - const char *string; +tilde_expand (const char *string) { char *result; int result_size, result_index; @@ -267,9 +263,7 @@ tilde_expand (string) non-null, the index of the end of the prefix into FNAME is returned in the location it points to. */ static char * -isolate_tilde_prefix (fname, lenp) - const char *fname; - int *lenp; +isolate_tilde_prefix (const char *fname, int *lenp) { char *ret; int i; @@ -293,9 +287,7 @@ isolate_tilde_prefix (fname, lenp) function. Right now, it just calls tilde_find_suffix and allocates new memory, but it can be expanded to do different things later. */ char * -tilde_find_word (fname, flags, lenp) - const char *fname; - int flags, *lenp; +tilde_find_word (const char *fname, int flags, int *lenp) { int x; char *r; @@ -323,10 +315,7 @@ tilde_find_word (fname, flags, lenp) /* Return a string that is PREFIX concatenated with SUFFIX starting at SUFFIND. */ static char * -glue_prefix_and_suffix (prefix, suffix, suffind) - char *prefix; - const char *suffix; - int suffind; +glue_prefix_and_suffix (char *prefix, const char *suffix, int suffind) { char *ret; int plen, slen; @@ -344,8 +333,7 @@ glue_prefix_and_suffix (prefix, suffix, suffind) tilde. If there is no expansion, call tilde_expansion_failure_hook. This always returns a newly-allocated string, never static storage. */ char * -tilde_expand_word (filename) - const char *filename; +tilde_expand_word (const char *filename) { char *dirname, *expansion, *username; int user_len; @@ -434,9 +422,7 @@ tilde_expand_word (filename) #undef NULL #include <stdio.h> -main (argc, argv) - int argc; - char **argv; +main (int argc, char **argv) { char *result, line[512]; int done = 0; @@ -464,11 +450,10 @@ main (argc, argv) exit (0); } -static void memory_error_and_abort (); +static void memory_error_and_abort (void); static void * -xmalloc (bytes) - size_t bytes; +xmalloc (size_t bytes) { void *temp = (char *)malloc (bytes); @@ -478,9 +463,7 @@ xmalloc (bytes) } static void * -xrealloc (pointer, bytes) - void *pointer; - int bytes; +xrealloc (void *pointer, int bytes) { void *temp; @@ -496,7 +479,7 @@ xrealloc (pointer, bytes) } static void -memory_error_and_abort () +memory_error_and_abort (void) { fprintf (stderr, "readline: out of virtual memory\n"); abort (); |
