fix off by one error when dequoting completed filenames; initial cut at readline identifying ANSI terminals; print coproc commands without coproc name if the coproc is a simple command

This commit is contained in:
Chet Ramey
2023-12-13 10:52:43 -05:00
parent ba57a3e752
commit 9d51df7546
10 changed files with 158 additions and 21 deletions
+31
View File
@@ -8141,3 +8141,34 @@ parse.y
parse.y,make_cmd.c
- read_a_line,make_here_document: if we're using shell_getc to read
the body of a here-document, let it manage line_number
12/8
----
bashline.c
- bash_dequote_filename: fix an off-by-one error that didn't remove a
closing single quote in a filename if it was backslash-escaped.
Report by Ole Tange <ota@prosa.dk>, fix from Grisha Levit <grishalevit@gmail.com>
lib/readline/terminal.c
- _rl_check_ansi_terminal: check whether or not rl_terminal_name
appears to be an ANSI/ECMA-48 terminal. Check some common terminal
types and then check whether some common terminal capabilities
(ce, nd, ho, up) begin with CSI (ESC-[) and then have a correct
subsequent character
- _rl_term_isansi: new variable, holds readline's idea about whether
the value of rl_terminal_name is an ANSI/ECMA-48 terminal. Initialized
to RL_ANSI_TERM_DEFAULT; set to the result of _rl_check_ansi_terminal
if initialized to 0 and on a `non-dumb' terminal
From an idea by John Tsiombikas <nuclear@mutantstargoat.com> in 11/2023
lib/readline/rlconf.h
- RL_ANSI_TERM_DEFAULT: define to 1 (yes) or 0 (no) to tell readline
whether or not to assume it's running on an ANSI/ECMA-48 terminal.
The default is 1 (yes)
12/11
-----
print_cmd.c
- make_command_string_internal: when printing a coproc, print the
coproc name only if the coproc command is not a simple command.
Report from Albert Akchurin <ackbeat@gmail.com>
+2 -1
View File
@@ -180,7 +180,8 @@ GCC_LINT_FLAGS = -O -Wall -Wshadow -Wpointer-arith -Wcast-qual -Wno-parentheses
-Wmissing-braces -Wuninitialized \
-Wmissing-declarations -Winline \
-Wmissing-prototypes -Wredundant-decls \
-Wformat-security -pedantic
-Wformat-security -pedantic \
-Werror=incompatible-pointer-types
GCC_LINT_CFLAGS = $(BASE_CCFLAGS) $(CPPFLAGS) $(GCC_LINT_FLAGS)
+4 -6
View File
@@ -4077,15 +4077,13 @@ bash_dequote_filename (char *text, int quote_char)
ret = (char *)xmalloc (l + 1);
for (quoted = quote_char, p = text, r = ret; p && *p; p++)
{
/* Allow backslash-escaped characters to pass through unscathed. */
if (*p == '\\')
/* Allow backslash-escaped characters to pass through unscathed. Backslashes
aren't special in single quotes. */
if (quoted != '\'' && *p == '\\')
{
/* Backslashes are preserved within single quotes. */
if (quoted == '\'')
*r++ = *p;
/* Backslashes are preserved within double quotes unless the
character is one that is defined to be escaped */
else if (quoted == '"' && ((sh_syntaxtab[(unsigned char)p[1]] & CBSDQUOTE) == 0))
if (quoted == '"' && ((sh_syntaxtab[(unsigned char)p[1]] & CBSDQUOTE) == 0))
*r++ = *p;
*r++ = *++p;
+5
View File
@@ -76,4 +76,9 @@
#define RL_VI_CMD_MODESTR_DEFAULT "(cmd)"
#define RL_VI_CMD_MODESTR_DEFLEN 5
/* Do you want readline to assume it's running in an ANSI-compatible terminal
by default? If set to 0, readline tries to check and verify whether or not
it is. */
#define RL_ANSI_TERM_DEFAULT 1 /* for now */
#endif /* _RLCONF_H_ */
+77 -4
View File
@@ -1,6 +1,6 @@
/* terminal.c -- controlling the terminal with termcap. */
/* Copyright (C) 1996-2022 Free Software Foundation, Inc.
/* Copyright (C) 1996-2023 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,7 @@ char PC, *BC, *UP;
char *_rl_term_clreol;
char *_rl_term_clrpag;
char *_rl_term_clrscroll;
char *_rl_term_ho;
char *_rl_term_cr;
char *_rl_term_backspace;
char *_rl_term_goto;
@@ -220,6 +221,9 @@ int _rl_enable_keypad;
/* Non-zero means the user wants to enable a meta key. */
int _rl_enable_meta = 1;
/* Non-zero means this is an ANSI-compatible terminal; assume it is. */
int _rl_term_isansi = RL_ANSI_TERM_DEFAULT;
#if defined (__EMX__)
static void
_emx_get_screensize (int *swp, int *shp)
@@ -433,6 +437,7 @@ static const struct _tc_string tc_strings[] =
{ "cr", &_rl_term_cr },
{ "dc", &_rl_term_dc },
{ "ei", &_rl_term_ei },
{ "ho", &_rl_term_ho },
{ "ic", &_rl_term_ic },
{ "im", &_rl_term_im },
{ "kD", &_rl_term_kD }, /* delete */
@@ -476,6 +481,63 @@ get_term_capabilities (char **bp)
tcap_initialized = 1;
}
struct _term_name {
const char * const name;
size_t len;
};
/* Non-exhaustive list of ANSI/ECMA terminals. */
static const struct _term_name ansiterms[] =
{
{ "xterm", 5 },
{ "rxvt", 4 },
{ "eterm", 5 },
{ "screen", 6 },
{ "tmux", 4 },
{ "vt100", 5 },
{ "vt102", 5 },
{ "vt220", 5 },
{ "vt320", 5 },
{ "ansi", 4 },
{ "scoansi", 7 },
{ "cygwin", 6 },
{ "linux", 5 },
{ "konsole", 7 },
{ "bvterm", 6 },
{ 0, 0 }
};
static inline int
iscsi (const char *s)
{
return ((s[0] == ESC && s[1] == '[') ? 2
: ((unsigned char)s[0] == 0x9b) ? 1 : 0);
}
static int
_rl_check_ansi_terminal (const char *terminal_name)
{
int i;
size_t len;
for (i = 0; ansiterms[i].name; i++)
if (STREQN (terminal_name, ansiterms[i].name, ansiterms[i].len))
return 1;
if (_rl_term_clreol == 0 || _rl_term_forward_char == 0 ||
_rl_term_ho == 0 || _rl_term_up == 0)
return 0;
/* check some common capabilities */
if (((len = iscsi (_rl_term_clreol)) && _rl_term_clreol[len] == 'K') && /* ce */
((len = iscsi (_rl_term_forward_char)) && _rl_term_forward_char[len] == 'C') && /* nd */
((len = iscsi (_rl_term_ho)) && _rl_term_ho[len] == 'H') && /* ho */
((len = iscsi (_rl_term_up)) && _rl_term_up[len] == 'A')) /* up */
return 1;
return 0;
}
int
_rl_init_terminal_io (const char *terminal_name)
{
@@ -490,7 +552,10 @@ _rl_init_terminal_io (const char *terminal_name)
if (term == 0)
term = "dumb";
dumbterm = STREQ (term, "dumb");
_rl_term_isansi = RL_ANSI_TERM_DEFAULT;
dumbterm = STREQ (term, "dumb") || STREQ (term, "vt52") || STREQ (term, "adm3a");
if (dumbterm)
_rl_term_isansi = 0;
reset_region_colors = 1;
@@ -502,6 +567,7 @@ _rl_init_terminal_io (const char *terminal_name)
_rl_terminal_can_insert = term_has_meta = _rl_term_autowrap = 0;
_rl_term_cr = "\r";
_rl_term_backspace = (char *)NULL;
_rl_term_ho = (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;
@@ -564,6 +630,7 @@ _rl_init_terminal_io (const char *terminal_name)
/* Everything below here is used by the redisplay code (tputs). */
_rl_screenchars = _rl_screenwidth * _rl_screenheight;
_rl_term_cr = "\r";
_rl_term_ho = (char *)NULL;
_rl_term_im = _rl_term_ei = _rl_term_ic = _rl_term_IC = (char *)NULL;
_rl_term_up = _rl_term_dc = _rl_term_DC = _rl_visible_bell = (char *)NULL;
_rl_term_ku = _rl_term_kd = _rl_term_kl = _rl_term_kr = (char *)NULL;
@@ -576,6 +643,8 @@ _rl_init_terminal_io (const char *terminal_name)
_rl_term_so = _rl_term_se = (char *)NULL;
_rl_terminal_can_insert = term_has_meta = 0;
_rl_term_isansi = 0; /* not an ANSI terminal */
/* Assume generic unknown terminal can't handle the enable/disable
escape sequences */
_rl_term_BD = _rl_term_BE = _rl_term_PE = _rl_term_PS = (char *)NULL;
@@ -637,9 +706,13 @@ _rl_init_terminal_io (const char *terminal_name)
bind_termcap_arrow_keys (vi_insertion_keymap);
#endif /* VI_MODE */
if (dumbterm == 0 && _rl_term_isansi == 0)
_rl_term_isansi = _rl_check_ansi_terminal (terminal_name);
/* There's no way to determine whether or not a given terminal supports
bracketed paste mode, so we assume a terminal named "dumb" does not. */
if (dumbterm)
bracketed paste mode, so we assume a non-ANSI terminal (as best as we
can determine) does not. */
if (_rl_term_isansi == 0)
_rl_enable_bracketed_paste = _rl_enable_active_region = 0;
if (reset_region_colors)
+3 -1
View File
@@ -355,7 +355,9 @@ make_command_string_internal (COMMAND *command)
break;
case cm_coproc:
cprintf ("coproc %s ", command->value.Coproc->name);
cprintf ("coproc ");
if (command->value.Coproc->command->type != cm_simple)
cprintf ("%s ", command->value.Coproc->name);
skip_this_indent++;
make_command_string_internal (command->value.Coproc->command);
break;
+2
View File
@@ -157,6 +157,8 @@ hello
world
hello
world
here-doc line 1
here-doc line 2
here-document
here-document
comsub here-string
+19 -9
View File
@@ -16,30 +16,40 @@
shopt -s expand_aliases
# single alias definition contains entire here-document
alias 'foo=cat <<EOF
alias 'heredoc=cat <<EOF
hello
world
EOF'
foo
heredoc
# here-document body continues after alias definition
alias 'foo=cat <<EOF
alias 'headplus=cat <<EOF
hello'
foo
headplus
world
EOF
unalias heredoc headplus
alias head='cat <<END'
head
here-doc line 1
here-doc line 2
END
# here-document delimiter in one alias, body in another
shopt -s expand_aliases
alias c='cat <<\END' d='c
alias head='cat <<\END' body='head
here-document
END'
d
body
# make sure delimiter is recognized whether the alias ends with a newline or not
shopt -s expand_aliases
alias c='cat <<\END' d='c
alias head='cat <<\END' body='head
here-document
END
'
d
body
unalias head body
+5
View File
@@ -134,6 +134,11 @@ EOF
);
echo "coprocs created"
}
mkcoprocs is a function
mkcoprocs ()
{
coproc cat -u - & read -u ${COPROC[0]} msg
}
cat is /bin/cat
cat is aliased to `echo cat'
/bin/cat
+10
View File
@@ -54,3 +54,13 @@ echo "coprocs created"
}
type mkcoprocs
unset -f mkcoprocs
# make sure that simple commands are printed without the coproc name
mkcoprocs ()
{
coproc cat -u - &
read -u ${COPROC[0]} msg
}
type mkcoprocs