fix a bug in word splitting that could potentially drop the first word; complete -p now prefixes the compspec for commands that begin with -' with --'; several builtins updated to use $'...' quoting for output when appropriate

This commit is contained in:
Chet Ramey
2026-04-02 11:02:52 -04:00
parent 55f721c51e
commit 1cbe8c04bb
14 changed files with 199 additions and 149 deletions
+22
View File
@@ -12809,3 +12809,25 @@ lib/glob/glob.c
doc/bash.1,doc/bashref.texi
- BASH_REMATCH: update [[ documentation to note that BASH_REMATCH can
be a local variable
3/20
----
subst.c
- word_list_quote_removal,word_list_split: fix initial setting of E
on first word split (RESULT == 0). If TRESULT expands to multiple
words, all but the first word were dropped because we didn't set
E to the end of the TRESULT list
3/30
----
builtins/complete.def
- print_cmd_name: prefix command names starting with `-' (however
unlikely) with `--'
Report from Étienne Barrié <etienne.barrie@gmail.com>
- print_cmd_name: use ansic_quote() to quote the command name if
necessary
builtins/type.def,builtins/complete.def,builtins/alias.def,builtins/type.def
print_cmd.c
- check for possible $'...' quoting and use it if appropriate instead
of just calling sh_single_quote()
+1 -1
View File
@@ -616,7 +616,7 @@ assoc_to_string (HASH_TABLE *h, char *sep, int quoted)
l = REVERSE_LIST(list, WORD_LIST *);
result = l ? string_list_internal (l, sep) : savestring ("");
result = l ? string_list_internal (l, sep, 0) : savestring ("");
dispose_words (l);
return result;
+4 -1
View File
@@ -226,7 +226,10 @@ print_alias (alias_t *alias, int flags)
{
char *value;
value = sh_single_quote (alias->value);
if (ansic_shouldquote (alias->value))
value = ansic_quote (alias->value, 0, (int *)0);
else
value = sh_single_quote (alias->value);
if (flags & AL_REUSABLE)
printf ("alias %s", (alias->name && alias->name[0] == '-') ? "-- " : "");
printf ("%s=%s\n", alias->name, value);
+20 -3
View File
@@ -540,7 +540,15 @@ print_arg (const char *arg, const char *flag, int quote)
if (arg)
{
x = quote ? sh_single_quote (arg) : (char *)arg;
if (quote)
{
if (ansic_shouldquote (arg))
x = ansic_quote (arg, 0, (int *)0);
else
x = sh_single_quote (arg);
}
else
x = (char *)arg;
printf ("%s %s ", flag, x);
if (x != arg)
free (x);
@@ -551,7 +559,10 @@ static void
print_cmd_name (const char *cmd)
{
char *x;
char *fmt;
fmt = (*cmd == '-') ? "-- %s" : "%s";
if (STREQ (cmd, DEFAULTCMD))
printf ("-D");
else if (STREQ (cmd, EMPTYCMD))
@@ -560,14 +571,20 @@ print_cmd_name (const char *cmd)
printf ("-I");
else if (*cmd == 0) /* XXX - can this happen? */
printf ("''");
else if (ansic_shouldquote (cmd))
{
x = ansic_quote (cmd, 0, (int *)0);
printf (fmt, x);
free (x);
}
else if (sh_contains_shell_metas (cmd))
{
x = sh_single_quote (cmd);
printf ("%s", x);
printf (fmt, x);
free (x);
}
else
printf ("%s", cmd);
printf (fmt, cmd);
}
static int
+6 -2
View File
@@ -301,8 +301,12 @@ showtrap (int i, int show_default)
}
else if (signal_is_hard_ignored (i))
t = (char *)NULL;
else
t = (p == (char *)IGNORE_SIG) ? (char *)NULL : sh_single_quote (p);
else if (p == (char *)IGNORE_SIG)
t = (char *)NULL;
else if (ansic_shouldquote (p))
t = ansic_quote (p, 0, (int *)0);
else
t = sh_single_quote (p);
sn = signal_name (i);
/* Make sure that signals whose names are unknown (for whatever reason)
+4 -1
View File
@@ -231,7 +231,10 @@ describe_command (char *command, int dflags)
printf (_("%s is aliased to `%s'\n"), command, alias->value);
else if (dflags & CDESC_REUSABLE)
{
x = sh_single_quote (alias->value);
if (ansic_shouldquote (alias->value))
x = ansic_quote (alias->value, 0, (int *)0);
else
x = sh_single_quote (alias->value);
printf ("alias %s=%s\n", command, x);
free (x);
}
+61 -61
View File
@@ -7265,7 +7265,7 @@ Any variable may be used as an indexed array; the declare builtin
explicitly declares an array. There is no maximum limit on the size of
an array, nor any requirement that members be indexed or assigned
contiguously. Indexed arrays are referenced using arithmetic
expressions that must expand to an integer (*note Shell Arithmetic::))
expressions that must expand to an integer (*note Shell Arithmetic::)
and are zero-based; associative arrays use arbitrary strings. Unless
otherwise noted, indexed array indices must be non-negative integers.
@@ -13812,66 +13812,66 @@ Node: Bash Conditional Expressions311088
Node: Shell Arithmetic316505
Node: Aliases319832
Node: Arrays322966
Node: The Directory Stack330669
Node: Directory Stack Builtins331466
Node: Controlling the Prompt335911
Node: The Restricted Shell338795
Node: Bash POSIX Mode341888
Node: Shell Compatibility Mode361704
Node: Job Control370711
Node: Job Control Basics371168
Node: Job Control Builtins377536
Node: Job Control Variables384324
Node: Command Line Editing385555
Node: Introduction and Notation387258
Node: Readline Interaction389610
Node: Readline Bare Essentials390798
Node: Readline Movement Commands392606
Node: Readline Killing Commands393602
Node: Readline Arguments395625
Node: Searching396715
Node: Readline Init File398958
Node: Readline Init File Syntax400261
Node: Conditional Init Constructs427212
Node: Sample Init File431597
Node: Bindable Readline Commands434717
Node: Commands For Moving436255
Node: Commands For History438719
Node: Commands For Text444110
Node: Commands For Killing448235
Node: Numeric Arguments451023
Node: Commands For Completion452175
Node: Keyboard Macros457871
Node: Miscellaneous Commands458572
Node: Readline vi Mode466115
Node: Programmable Completion467092
Node: Programmable Completion Builtins476828
Node: A Programmable Completion Example488565
Node: Using History Interactively493910
Node: Bash History Facilities494591
Node: Bash History Builtins498326
Node: History Interaction505921
Node: Event Designators510871
Node: Word Designators512449
Node: Modifiers514841
Node: Installing Bash516778
Node: Basic Installation517894
Node: Compilers and Options521770
Node: Compiling For Multiple Architectures522520
Node: Installation Names524273
Node: Specifying the System Type526507
Node: Sharing Defaults527253
Node: Operation Controls527967
Node: Optional Features528986
Node: Reporting Bugs541709
Node: Major Differences From The Bourne Shell543066
Node: GNU Free Documentation License564493
Node: Indexes589670
Node: Builtin Index590121
Node: Reserved Word Index597219
Node: Variable Index599664
Node: Function Index617077
Node: Concept Index631210
Node: The Directory Stack330668
Node: Directory Stack Builtins331465
Node: Controlling the Prompt335910
Node: The Restricted Shell338794
Node: Bash POSIX Mode341887
Node: Shell Compatibility Mode361703
Node: Job Control370710
Node: Job Control Basics371167
Node: Job Control Builtins377535
Node: Job Control Variables384323
Node: Command Line Editing385554
Node: Introduction and Notation387257
Node: Readline Interaction389609
Node: Readline Bare Essentials390797
Node: Readline Movement Commands392605
Node: Readline Killing Commands393601
Node: Readline Arguments395624
Node: Searching396714
Node: Readline Init File398957
Node: Readline Init File Syntax400260
Node: Conditional Init Constructs427211
Node: Sample Init File431596
Node: Bindable Readline Commands434716
Node: Commands For Moving436254
Node: Commands For History438718
Node: Commands For Text444109
Node: Commands For Killing448234
Node: Numeric Arguments451022
Node: Commands For Completion452174
Node: Keyboard Macros457870
Node: Miscellaneous Commands458571
Node: Readline vi Mode466114
Node: Programmable Completion467091
Node: Programmable Completion Builtins476827
Node: A Programmable Completion Example488564
Node: Using History Interactively493909
Node: Bash History Facilities494590
Node: Bash History Builtins498325
Node: History Interaction505920
Node: Event Designators510870
Node: Word Designators512448
Node: Modifiers514840
Node: Installing Bash516777
Node: Basic Installation517893
Node: Compilers and Options521769
Node: Compiling For Multiple Architectures522519
Node: Installation Names524272
Node: Specifying the System Type526506
Node: Sharing Defaults527252
Node: Operation Controls527966
Node: Optional Features528985
Node: Reporting Bugs541708
Node: Major Differences From The Bourne Shell543065
Node: GNU Free Documentation License564492
Node: Indexes589669
Node: Builtin Index590120
Node: Reserved Word Index597218
Node: Variable Index599663
Node: Function Index617076
Node: Concept Index631209

End Tag Table
BIN
View File
Binary file not shown.
+61 -61
View File
@@ -7266,7 +7266,7 @@ Any variable may be used as an indexed array; the declare builtin
explicitly declares an array. There is no maximum limit on the size of
an array, nor any requirement that members be indexed or assigned
contiguously. Indexed arrays are referenced using arithmetic
expressions that must expand to an integer (*note Shell Arithmetic::))
expressions that must expand to an integer (*note Shell Arithmetic::)
and are zero-based; associative arrays use arbitrary strings. Unless
otherwise noted, indexed array indices must be non-negative integers.
@@ -13813,66 +13813,66 @@ Node: Bash Conditional Expressions311295
Node: Shell Arithmetic316715
Node: Aliases320045
Node: Arrays323182
Node: The Directory Stack330888
Node: Directory Stack Builtins331688
Node: Controlling the Prompt336136
Node: The Restricted Shell339023
Node: Bash POSIX Mode342119
Node: Shell Compatibility Mode361938
Node: Job Control370948
Node: Job Control Basics371408
Node: Job Control Builtins377779
Node: Job Control Variables384570
Node: Command Line Editing385804
Node: Introduction and Notation387510
Node: Readline Interaction389865
Node: Readline Bare Essentials391056
Node: Readline Movement Commands392867
Node: Readline Killing Commands393866
Node: Readline Arguments395892
Node: Searching396985
Node: Readline Init File399231
Node: Readline Init File Syntax400537
Node: Conditional Init Constructs427491
Node: Sample Init File431879
Node: Bindable Readline Commands435002
Node: Commands For Moving436543
Node: Commands For History439010
Node: Commands For Text444404
Node: Commands For Killing448532
Node: Numeric Arguments451323
Node: Commands For Completion452478
Node: Keyboard Macros458177
Node: Miscellaneous Commands458881
Node: Readline vi Mode466427
Node: Programmable Completion467407
Node: Programmable Completion Builtins477146
Node: A Programmable Completion Example488886
Node: Using History Interactively494234
Node: Bash History Facilities494918
Node: Bash History Builtins498656
Node: History Interaction506254
Node: Event Designators511207
Node: Word Designators512788
Node: Modifiers515183
Node: Installing Bash517123
Node: Basic Installation518242
Node: Compilers and Options522121
Node: Compiling For Multiple Architectures522874
Node: Installation Names524630
Node: Specifying the System Type526867
Node: Sharing Defaults527616
Node: Operation Controls528333
Node: Optional Features529355
Node: Reporting Bugs542081
Node: Major Differences From The Bourne Shell543441
Node: GNU Free Documentation License564871
Node: Indexes590051
Node: Builtin Index590505
Node: Reserved Word Index597606
Node: Variable Index600054
Node: Function Index617470
Node: Concept Index631606
Node: The Directory Stack330887
Node: Directory Stack Builtins331687
Node: Controlling the Prompt336135
Node: The Restricted Shell339022
Node: Bash POSIX Mode342118
Node: Shell Compatibility Mode361937
Node: Job Control370947
Node: Job Control Basics371407
Node: Job Control Builtins377778
Node: Job Control Variables384569
Node: Command Line Editing385803
Node: Introduction and Notation387509
Node: Readline Interaction389864
Node: Readline Bare Essentials391055
Node: Readline Movement Commands392866
Node: Readline Killing Commands393865
Node: Readline Arguments395891
Node: Searching396984
Node: Readline Init File399230
Node: Readline Init File Syntax400536
Node: Conditional Init Constructs427490
Node: Sample Init File431878
Node: Bindable Readline Commands435001
Node: Commands For Moving436542
Node: Commands For History439009
Node: Commands For Text444403
Node: Commands For Killing448531
Node: Numeric Arguments451322
Node: Commands For Completion452477
Node: Keyboard Macros458176
Node: Miscellaneous Commands458880
Node: Readline vi Mode466426
Node: Programmable Completion467406
Node: Programmable Completion Builtins477145
Node: A Programmable Completion Example488885
Node: Using History Interactively494233
Node: Bash History Facilities494917
Node: Bash History Builtins498655
Node: History Interaction506253
Node: Event Designators511206
Node: Word Designators512787
Node: Modifiers515182
Node: Installing Bash517122
Node: Basic Installation518241
Node: Compilers and Options522120
Node: Compiling For Multiple Architectures522873
Node: Installation Names524629
Node: Specifying the System Type526866
Node: Sharing Defaults527615
Node: Operation Controls528332
Node: Optional Features529354
Node: Reporting Bugs542080
Node: Major Differences From The Bourne Shell543440
Node: GNU Free Documentation License564870
Node: Indexes590050
Node: Builtin Index590504
Node: Reserved Word Index597605
Node: Variable Index600053
Node: Function Index617469
Node: Concept Index631605

End Tag Table
+1 -1
View File
@@ -8704,7 +8704,7 @@ There is no maximum
limit on the size of an array, nor any requirement that members
be indexed or assigned contiguously.
Indexed arrays are referenced using arithmetic expressions
that must expand to an integer (@pxref{Shell Arithmetic}))
that must expand to an integer (@pxref{Shell Arithmetic})
and are zero-based;
associative arrays use arbitrary strings.
Unless otherwise noted, indexed array indices must be non-negative integers.
+1 -1
View File
@@ -6782,7 +6782,7 @@ error_token_from_token (int tok)
break;
case ARITH_FOR_EXPRS:
if (yylval.word_list)
t = string_list_internal (yylval.word_list, " ; ");
t = string_list_internal (yylval.word_list, " ; ", 0);
break;
case COND_CMD:
t = (char *)NULL; /* punt */
+4 -1
View File
@@ -1132,7 +1132,10 @@ print_heredoc_header (REDIRECT *redirect)
/* If the here document delimiter is quoted, single-quote it. */
if (redirect->redirectee.filename->flags & W_QUOTED)
{
x = sh_single_quote (redirect->here_doc_eof);
if (ansic_shouldquote (redirect->here_doc_eof))
x = ansic_quote (redirect->here_doc_eof, 0, (int *)0);
else
x = sh_single_quote (redirect->here_doc_eof);
cprintf ("<<%s%s", kill_leading ? "-" : "", x);
free (x);
}
+13 -15
View File
@@ -2851,7 +2851,7 @@ assignment_name (const char *string)
/* Return a single string of all the words in LIST. SEP is the separator
to put between individual elements of LIST in the output string. */
char *
string_list_internal (WORD_LIST *list, char *sep)
string_list_internal (WORD_LIST *list, char *sep, int flags)
{
register WORD_LIST *t;
char *result, *r;
@@ -2904,7 +2904,7 @@ string_list_internal (WORD_LIST *list, char *sep)
char *
string_list (WORD_LIST *list)
{
return (string_list_internal (list, " "));
return (string_list_internal (list, " ", 0));
}
/* An external interface that can be used by the rest of the shell to
@@ -2982,7 +2982,7 @@ string_list_dollar_star (WORD_LIST *list, int quoted, int flags)
sep[1] = '\0';
#endif
ret = string_list_internal (list, sep);
ret = string_list_internal (list, sep, 0);
#if defined (HANDLE_MULTIBYTE) && !defined (__GNUC__)
free (sep);
#endif
@@ -3064,7 +3064,7 @@ string_list_dollar_at (WORD_LIST *list, int quoted, int flags)
? quote_list (list)
: list_quote_escapes (list);
ret = string_list_internal (tlist, sep);
ret = string_list_internal (tlist, sep, 0);
#if defined (HANDLE_MULTIBYTE) && !defined (__GNUC__)
free (sep);
#endif
@@ -8179,7 +8179,7 @@ parameter_brace_expand_rhs (char *name, char *value,
string_list_dollar_star for "$@" otherwise. */
if (l->next && ifs_is_null)
{
temp = string_list_internal (l, " ");
temp = string_list_internal (l, " ", 0);
w->flags |= W_SPLITSPACE;
}
else if (l_hasdollat || l->next)
@@ -12452,11 +12452,10 @@ word_list_quote_removal (WORD_LIST *list, int quoted)
if (result == 0)
result = e = tresult;
else
{
e->next = tresult;
while (e->next)
e = e->next;
}
e->next = tresult;
while (e && e->next)
e = e->next;
}
return (result);
}
@@ -12584,11 +12583,10 @@ word_list_split (WORD_LIST *list)
if (result == 0)
result = e = tresult;
else
{
e->next = tresult;
while (e->next)
e = e->next;
}
e->next = tresult;
while (e && e->next)
e = e->next;
}
return (result);
}
+1 -1
View File
@@ -118,7 +118,7 @@ extern char *assignment_name (const char *);
/* Return a single string of all the words present in LIST, separating
each word with SEP. */
extern char *string_list_internal (WORD_LIST *, char *);
extern char *string_list_internal (WORD_LIST *, char *, int);
/* Return a single string of all the words present in LIST, separating
each word with a space. */