fix for multi-level alias expansion with trailing space

This commit is contained in:
Chet Ramey
2023-01-18 13:59:27 -05:00
parent a5d2617c7a
commit 992bd861ab
4 changed files with 185 additions and 23 deletions
+31
View File
@@ -5057,3 +5057,34 @@ execute_cmd.c
and isn't trapped, restore the old handler
- setup_async_signals: call set_signal_async_ignored to set the right
flags
1/16
----
parse.y
- read_token_word: if we're in posix mode, and we find a reserved word
before checking a token for aliases, turn off the `check next word
for aliases' flag (PST_ALEXPNEXT). This is for compatibility with
other shells. From a report by <anonymous4feedback@outlook.com>
- shell_getc: make sure the shell is reading a buffered stream before
checking the default buffered stream for errors if yy_getc returns 0
1/17
----
subst.c
- split_at_delims: if the cursor is at whitespace just preceding a
word, and we're doing this for completion (e.g., to build COMP_WORDS),
force the creation of an empty word and set the current word to it.
This is a change from previous behavior, but a useful one: it makes
COMP_WORDS[COMP_CWORD] and $2 to a completion function consistent
and the same as the word readline wants to complete. From a report
from Naim Favier <n@monade.li> back in 6/2022
parse.y
- read_token: turn off PST_ALEXPNEXT if we read a shell metacharacter:
we will expand aliases anyway if the token puts the shell in a
command word position and we took pains to turn it off for
redirection tokens; remove special cases that turned it off
- pop_string: don't turn off PST_ALEXPNEXT if it's on; this is what
prevents it from being enabled if an alias expansion of more than
two aliases ends with a space. Fixes issue reported by
<anonymous4feedback@outlook.com>
+149 -20
View File
@@ -152,6 +152,11 @@ extern int errno;
static void debug_parser (int);
#endif
#if defined (DEBUG)
static void dump_tflags (int);
static void dump_pflags (int);
#endif
static int yy_getc (void);
static int yy_ungetc (int);
@@ -1934,9 +1939,6 @@ push_string (char *s, int expand, alias_t *ap)
shell_input_line_size = shell_input_line_len = STRLEN (s);
shell_input_line_index = 0;
shell_input_line_terminator = '\0';
#if 0
parser_state &= ~PST_ALEXPNEXT; /* XXX */
#endif
set_line_mbstate ();
}
@@ -1962,8 +1964,6 @@ pop_string (void)
#if defined (ALIAS)
if (pushed_string_list->expand_alias)
parser_state |= PST_ALEXPNEXT;
else
parser_state &= ~PST_ALEXPNEXT;
#endif
t = pushed_string_list;
@@ -2439,7 +2439,7 @@ shell_getc (int remove_quoted_newline)
if (i == 0)
shell_input_line_terminator = EOF;
#if defined (BUFFERED_INPUT)
if (i == 0)
if (i == 0 && bash_input.type == st_bstream)
{
BUFFERED_STREAM *bp;
bp = get_buffered_stream (default_buffered_input);
@@ -3024,6 +3024,8 @@ static int open_brace_count;
word_lineno[word_top] = line_number; \
} \
\
if (posixly_correct) \
parser_state &= ~PST_ALEXPNEXT; \
return (word_token_alist[i].token); \
} \
} \
@@ -3381,6 +3383,7 @@ read_token (int command)
word_desc_to_read = (WORD_DESC *)NULL;
}
token_to_read = 0;
/* XXX - PST_ALEXPNEXT? */
return (result);
}
@@ -3459,10 +3462,9 @@ read_token (int command)
if MBTEST(shellmeta (character))
{
#if defined (ALIAS)
/* Turn off alias tokenization iff this character sequence would
not leave us ready to read a command. */
if (character == '<' || character == '>')
parser_state &= ~PST_ALEXPNEXT;
/* Turn off alias tokenization, we will perform alias expansion on the
next command word if it's one where a command word is acceptable. */
parser_state &= ~PST_ALEXPNEXT;
#endif /* ALIAS */
parser_state &= ~PST_ASSIGNOK;
@@ -3500,10 +3502,6 @@ read_token (int command)
case ';':
parser_state |= PST_CASEPAT;
#if defined (ALIAS)
parser_state &= ~PST_ALEXPNEXT;
#endif /* ALIAS */
peek_char = shell_getc (1);
if MBTEST(peek_char == '&')
return (SEMI_SEMI_AND);
@@ -3553,9 +3551,6 @@ read_token (int command)
else if MBTEST(character == ';' && peek_char == '&')
{
parser_state |= PST_CASEPAT;
#if defined (ALIAS)
parser_state &= ~PST_ALEXPNEXT;
#endif /* ALIAS */
return (SEMI_AND);
}
@@ -3567,9 +3562,6 @@ read_token (int command)
if MBTEST(character == ')' && last_read_token == '(' && token_before_that == WORD)
{
parser_state |= PST_ALLOWOPNBRC;
#if defined (ALIAS)
parser_state &= ~PST_ALEXPNEXT;
#endif /* ALIAS */
save_dstart = function_dstart;
function_dstart = line_number;
}
@@ -4067,6 +4059,143 @@ dump_tflags (int flags)
fprintf (stderr, "\n");
fflush (stderr);
}
static void
dump_pflags (int flags)
{
int f;
f = flags;
fprintf (stderr, "%d -> ", f);
if (f & PST_CASEPAT)
{
f &= ~PST_CASEPAT;
fprintf (stderr, "PST_CASEPAT%s", f ? "|" : "");
}
if (f & PST_ALEXPNEXT)
{
f &= ~PST_ALEXPNEXT;
fprintf (stderr, "PST_ALEXPNEXT%s", f ? "|" : "");
}
if (f & PST_ALLOWOPNBRC)
{
f &= ~PST_ALLOWOPNBRC;
fprintf (stderr, "PST_ALLOWOPNBRC%s", f ? "|" : "");
}
if (f & PST_NEEDCLOSBRC)
{
f &= ~PST_NEEDCLOSBRC;
fprintf (stderr, "PST_NEEDCLOSBRC%s", f ? "|" : "");
}
if (f & PST_DBLPAREN)
{
f &= ~PST_DBLPAREN;
fprintf (stderr, "PST_DBLPAREN%s", f ? "|" : "");
}
if (f & PST_SUBSHELL)
{
f &= ~PST_SUBSHELL;
fprintf (stderr, "PST_SUBSHELL%s", f ? "|" : "");
}
if (f & PST_CMDSUBST)
{
f &= ~PST_CMDSUBST;
fprintf (stderr, "PST_CMDSUBST%s", f ? "|" : "");
}
if (f & PST_CASESTMT)
{
f &= ~PST_CASESTMT;
fprintf (stderr, "PST_CASESTMT%s", f ? "|" : "");
}
if (f & PST_CONDCMD)
{
f &= ~PST_CONDCMD;
fprintf (stderr, "PST_CONDCMD%s", f ? "|" : "");
}
if (f & PST_CONDEXPR)
{
f &= ~PST_CONDEXPR;
fprintf (stderr, "PST_CONDEXPR%s", f ? "|" : "");
}
if (f & PST_ARITHFOR)
{
f &= ~PST_ARITHFOR;
fprintf (stderr, "PST_ARITHFOR%s", f ? "|" : "");
}
if (f & PST_ALEXPAND)
{
f &= ~PST_ALEXPAND;
fprintf (stderr, "PST_ALEXPAND%s", f ? "|" : "");
}
if (f & PST_EXTPAT)
{
f &= ~PST_EXTPAT;
fprintf (stderr, "PST_EXTPAT%s", f ? "|" : "");
}
if (f & PST_COMPASSIGN)
{
f &= ~PST_COMPASSIGN;
fprintf (stderr, "PST_COMPASSIGN%s", f ? "|" : "");
}
if (f & PST_ASSIGNOK)
{
f &= ~PST_ASSIGNOK;
fprintf (stderr, "PST_ASSIGNOK%s", f ? "|" : "");
}
if (f & PST_EOFTOKEN)
{
f &= ~PST_EOFTOKEN;
fprintf (stderr, "PST_EOFTOKEN%s", f ? "|" : "");
}
if (f & PST_REGEXP)
{
f &= ~PST_REGEXP;
fprintf (stderr, "PST_REGEXP%s", f ? "|" : "");
}
if (f & PST_HEREDOC)
{
f &= ~PST_HEREDOC;
fprintf (stderr, "PST_HEREDOC%s", f ? "|" : "");
}
if (f & PST_REPARSE)
{
f &= ~PST_REPARSE;
fprintf (stderr, "PST_REPARSE%s", f ? "|" : "");
}
if (f & PST_REDIRLIST)
{
f &= ~PST_REDIRLIST;
fprintf (stderr, "PST_REDIRLIST%s", f ? "|" : "");
}
if (f & PST_COMMENT)
{
f &= ~PST_COMMENT;
fprintf (stderr, "PST_COMMENT%s", f ? "|" : "");
}
if (f & PST_ENDALIAS)
{
f &= ~PST_ENDALIAS;
fprintf (stderr, "PST_ENDALIAS%s", f ? "|" : "");
}
if (f & PST_NOEXPAND)
{
f &= ~PST_NOEXPAND;
fprintf (stderr, "PST_NOEXPAND%s", f ? "|" : "");
}
if (f & PST_NOERROR)
{
f &= ~PST_NOERROR;
fprintf (stderr, "PST_NOERROR%s", f ? "|" : "");
}
if (f & PST_STRING)
{
f &= ~PST_STRING;
fprintf (stderr, "PST_STRING%s", f ? "|" : "");
}
fprintf (stderr, "\n");
fflush (stderr);
}
#endif
/* Parse a $(...) command substitution. This reads input from the current
+1 -1
View File
@@ -29,7 +29,7 @@
#define PST_CASEPAT 0x000001 /* in a case pattern list */
#define PST_ALEXPNEXT 0x000002 /* expand next word for aliases */
#define PST_ALLOWOPNBRC 0x000004 /* allow open brace for function def */
#define PST_NEEDCLOSBRC 0x000008 /* need close brace */
#define PST_NEEDCLOSBRC 0x000008 /* need close brace -- unused */
#define PST_DBLPAREN 0x000010 /* double-paren parsing - unused */
#define PST_SUBSHELL 0x000020 /* ( ... ) subshell */
#define PST_CMDSUBST 0x000040 /* $( ... ) command substitution */
+4 -2
View File
@@ -2644,8 +2644,10 @@ split_at_delims (const char *string, int slen, const char *delims, int sentinel,
cw = nw;
/* If the cursor is at whitespace just before word start, set the
sentinel word to the current word. */
if (cwp && cw == -1 && sentinel == ts-1)
sentinel word to the current word. We don't do this if this is
being called as part of completion, since readline attempts
completion on empty words in this case. */
if ((flags & SD_COMPLETE) == 0 && cwp && cw == -1 && sentinel == ts-1)
cw = nw;
/* If the cursor is at whitespace between two words, make a new, empty