diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index 65f4c95b..ab59fcd1 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -12311,3 +12311,19 @@ execute_cmd.c - execute_in_subshell: clear the exit trap before checking for a pending fatal signal From https://savannah.gnu.org/bugs/?67745 + + 12/2 + ---- +builtins/printf.def + - import %N$ specifier implementation from printf-nspecifier branch; + implementation is similar to coreutils'. + - we warn about mixing numbered and unnumbered format specifiers in + posix mode + - getint: now takes second argument to deal with numbered specifiers + - getstar: new function to get precision and fieldwidth from argument + list if `*' in format specifier, handling numbered arguments + - narg, nptr: we build a new format string as necessary + Originally from https://savannah.gnu.org/support/?111166, also + discussed in thread starting with + https://lists.gnu.org/archive/html/bug-bash/2025-02/msg00151.html + diff --git a/MANIFEST b/MANIFEST index d1b00de7..f9af056b 100644 --- a/MANIFEST +++ b/MANIFEST @@ -1442,6 +1442,7 @@ tests/printf4.sub f tests/printf5.sub f tests/printf6.sub f tests/printf7.sub f +tests/printf8.sub f tests/procsub.tests f tests/procsub.right f tests/procsub1.sub f diff --git a/builtins/printf.def b/builtins/printf.def index 2bb70581..b3622017 100644 --- a/builtins/printf.def +++ b/builtins/printf.def @@ -100,6 +100,8 @@ extern int errno; { \ QUIT; \ retval = value; \ + if (narg_argc != -1) \ + free (narg_argv); \ if (conv_bufsize > 4096 ) \ { \ free (conv_buf); \ @@ -178,6 +180,10 @@ extern int errno; #define LENMODS "hjlLtz" #define DIGITS "0123456789" +#ifndef NL_ARGMAX +# define NL_ARGMAX 999 +#endif + #ifndef TIMELEN_MAX # define TIMELEN_MAX 128 #endif @@ -202,7 +208,8 @@ static int vbprintf (const char *, ...) __attribute__((__format__ (printf, 1, 2) static char *mklong (char *, char *, size_t); static int getchr (void); static char *getstr (void); -static int getint (int); +static int getint (int, int); +static int getstar (char **, int); static intmax_t getintmax (void); static uintmax_t getuintmax (void); @@ -247,12 +254,42 @@ static size_t vblen; static char **narg_argv; static int narg_argc; static int narg_maxind; +static int narg_numind; /* last numbered argument specification */ +static int narg_seqind; /* only used when mixing numbered and unnumbered conversions */ +static int narg_base; /* used on format reuse */ +static char *narg_arg; /* argument corresponding to the numbered conversion spec */ +static int narg_convtype; /* 1 = numbered, 0 = unnumbered */ +static int narg_convwarned; /* want to minimize the warnings */ +static char *nfmt = 0; static intmax_t tw; static char *conv_buf; static size_t conv_bufsize; +static void +init_numarg () +{ + size_t len; + WORD_LIST *l; + + len = list_length ((GENERIC_LIST *)orig_arglist); + narg_argv = (char **)xmalloc ((len + 2) * sizeof (char *)); /* +2 because we don't use 0 */ + + for (narg_argc = 1, l = orig_arglist; l; l = l->next) + narg_argv[narg_argc++] = l->word->word; + + /* If we've processed some unnumbered conversion specifications before + we get the first numbered one, count those as "previous conversion + specifications that consumed an argument." */ + for (narg_seqind = 0, l = orig_arglist; l != garglist; l = l->next) + narg_seqind++; + + narg_argv[narg_argc] = NULL; + narg_maxind = narg_numind = narg_base = 0; + narg_arg = NULL; +} + static inline int decodeint (char **str, int diagnose, int overflow_return) { @@ -281,7 +318,10 @@ printf_builtin (WORD_LIST *list) { int ch, fieldwidth, precision; int have_fieldwidth, have_precision, use_Lmod, altform, longform; + int moreargs; char convch, thisch, nextch, *format, *modstart, *precstart, *fmt, *start; + char *nptr, *origfmt; + size_t nargind; #if defined (HANDLE_MULTIBYTE) char mbch[25]; /* 25 > MB_LEN_MAX, plus can handle 4-byte UTF-8 and large Unicode characters*/ int mbind, mblen, mb_cur_max; @@ -293,6 +333,8 @@ printf_builtin (WORD_LIST *list) conversion_error = 0; vflag = 0; + narg_argc = -1; + reset_internal_getopt (); while ((ch = internal_getopt (list, "v:")) != -1) { @@ -357,15 +399,23 @@ printf_builtin (WORD_LIST *list) mb_cur_max = MB_CUR_MAX; + nfmt = xrealloc (nfmt, strlen (format) + 1); /* XXX error checking */ + nfmt[0] = '\0'; + /* Basic algorithm is to scan the format string for conversion specifications -- once one is found, find out if the field width or precision is a '*'; if it is, gather up value. Note, format strings are reused as necessary to use up the provided arguments, arguments of zero/null string are provided to use up the format string. */ + + /* We only warn once, even if we reuse the format, and we only warn in + posix mode. */ + narg_convwarned = !posixly_correct; do { tw = 0; + /* find next format specification */ for (fmt = format; *fmt; fmt++) { @@ -409,7 +459,9 @@ printf_builtin (WORD_LIST *list) } /* ASSERT(*fmt == '%') */ - start = fmt++; + origfmt = fmt; /* saved for format errors */ + nptr = start = nfmt; /* we construct our own format string */ + *nptr++ = *fmt++; if (*fmt == '%') /* %% prints a % */ { @@ -417,37 +469,117 @@ printf_builtin (WORD_LIST *list) continue; } + narg_convtype = 0; + /* Look for possible %N$ numbered conversion specifier. */ + /* "Conversions can be applied to the nth argument operand rather + than to the next argument operand. In this case, the conversion + specifier character '%' is replaced by the sequence "%n$", + where n is a decimal integer in the range [1,{NL_ARGMAX}], + giving the argument operand number. This feature provides for + the definition of format strings that select arguments in an + order appropriate to specific languages." */ + /* This leaves nargv_curind pointing to the argument corresponding + to the numbered conversion spec or the next sequential one after + having processed a numbered spec, so the advancearg() in the + various code handling the conversion specifiers advances it. */ + /* We don't allow N$ for precision or field width at this time. */ + nargind = strspn (fmt, DIGITS); + if (nargind > 0 && fmt[nargind] == '$') + { + char *ep; + int narg, thisarg; + + if (garglist != orig_arglist && narg_convwarned == 0) + { + builtin_warning ("%s", _("should not mix numbered and unnumbered conversions")); + narg_convwarned = 1; + } + if (narg_argc == -1) + init_numarg (); + thisarg = (int)strtol (fmt, &ep, 10); + /* "If it is a numbered argument conversion specification, + printf should write a diagnostic message to standard error + and exit with non-zero status" */ + if (thisarg <= 0 || thisarg >= narg_argc) + { + /* We don't want to print this error message for numbered + conversions exceeding the number of arguments unless + we are in posix mode, so we set narg_numind = narg_argc + if we are not. */ + if (thisarg <= 0 || posixly_correct) + { + builtin_error (_("%d: numbered conversion out of range"), thisarg); + PRETURN (EXECUTION_FAILURE); + } + thisarg = narg_argc; + } + thisarg += narg_base; + narg_numind = (thisarg < narg_argc) ? thisarg : narg_argc; + if (narg_numind > narg_maxind) + narg_maxind = narg_numind; + narg_arg = narg_argv[narg_numind]; + narg_convtype = 1; + fmt += nargind + 1; + } + else if (narg_argc != -1) + { + int thisarg; + + if (narg_convwarned == 0) + { + builtin_warning ("%s", _("should not mix numbered and unnumbered conversions")); + narg_convwarned = 1; + } + /* There is genuine incompatibility here between macOS/FreeBSD + printf and coreutils printf. + Given '%s %3$s %s\n' A B C D, coreutils printf treats the + unnumbered coversion specs sequentially, so it echoes "A C B", + then "D" on a new line. + FreeBSD printf treats the next unnumbered specifier following + a numbered specifier as numbered + 1, and prints "A C D". + zsh and ksh93 are like coreutils; mksh is like FreeBSD. + We follow coreutils here for now, but subject to change. */ + narg_arg = (narg_seqind < narg_argc) ? narg_argv[++narg_seqind] : NULL; + if (narg_seqind > narg_maxind) + narg_maxind = narg_seqind; + } + /* Found format specification, skip to field width. We check for alternate form for possible later use. */ - for (; *fmt && strchr(SKIP1, *fmt); ++fmt) - if (*fmt == '#') - altform++; + while (*fmt && strchr(SKIP1, *fmt)) + { + if (*fmt == '#') + altform++; + *nptr++ = *fmt++; /* build format string */ + } + *nptr = '\0'; /* Skip optional field width. */ if (*fmt == '*') { - fmt++; + *nptr++ = *fmt++; have_fieldwidth = 1; /* Handle field with overflow by ignoring fieldwidth for now. - getint() prints a message. */ - fieldwidth = getint (0); + getstar() prints a message. */ + fieldwidth = getstar (&fmt, 0); } else while (DIGIT (*fmt)) - fmt++; + *nptr++ = *fmt++; + *nptr = '\0'; /* Skip optional '.' and precision */ if (*fmt == '.') { - ++fmt; + *nptr++ = *fmt++; if (*fmt == '*') { - fmt++; + *nptr++ = *fmt++; have_precision = 1; /* Handle precision overflow by ignoring precision for now. - getint() prints a message. + getstar() prints a message. "A negative precision is treated as if it were missing." */ - precision = getint (-1); + precision = getstar (&fmt, -1); } else { @@ -460,12 +592,13 @@ printf_builtin (WORD_LIST *list) #else if (*fmt == '-') #endif - fmt++; + *nptr++ = *fmt++; if (DIGIT (*fmt)) precstart = fmt; while (DIGIT (*fmt)) - fmt++; + *nptr++ = *fmt++; } + *nptr = '\0'; } /* skip possible format modifiers */ @@ -475,7 +608,7 @@ printf_builtin (WORD_LIST *list) { use_Lmod |= USE_LONG_DOUBLE && *fmt == 'L'; longform |= *fmt == 'l'; - fmt++; + *nptr++ = *fmt++; } if (*fmt == 0) @@ -484,6 +617,9 @@ printf_builtin (WORD_LIST *list) PRETURN (EXECUTION_FAILURE); } + *nptr++ = *fmt; + *nptr = '\0'; + convch = *fmt; thisch = modstart[0]; nextch = modstart[1]; @@ -607,7 +743,7 @@ printf_builtin (WORD_LIST *list) if (*fmt != ')' || *++fmt != 'T') { builtin_warning (_("`%c': invalid time format specification"), *fmt); - fmt = start; + fmt = origfmt; free (timefmt); PC (*fmt); continue; @@ -620,7 +756,10 @@ printf_builtin (WORD_LIST *list) } /* argument is seconds since the epoch with special -1 and -2 */ /* default argument is equivalent to -1; special case */ - arg = garglist ? getintmax () : -1; + if (narg_argc != -1) + arg = (narg_numind < narg_argc && narg_argv[narg_numind]) ? getintmax (): -1; + else + arg = garglist ? getintmax () : -1; if (arg == -1) secs = NOW; /* roughly date +%s */ else if (arg == -2) @@ -643,8 +782,8 @@ printf_builtin (WORD_LIST *list) else timebuf[sizeof(timebuf) - 1] = '\0'; /* convert to %s format that preserves fieldwidth and precision */ - modstart[0] = 's'; - modstart[1] = '\0'; + *nptr++ = 's'; + *nptr = '\0'; r = printstr (start, timebuf, strlen (timebuf), fieldwidth, precision); /* XXX - %s for now */ if (r < 0) PRETURN (EXECUTION_FAILURE); @@ -821,8 +960,44 @@ printf_builtin (WORD_LIST *list) /* PRETURN will print error message. */ PRETURN (EXECUTION_FAILURE); } + + /* "The format operand shall be reused as often as necessary to satisfy + the argument operands. If conversion specifications beginning with + a "%n$" sequence are used, on format reuse the value of n shall + refer to the nth argument operand following the highest numbered + argument operand consumed by the previous use of the format operand." */ + if (narg_argc != -1) + { + /* If we consumed the last argument, we're done. */ + moreargs = (narg_numind < narg_argc) && (narg_maxind < narg_argc) && (narg_seqind < narg_argc); + narg_base = narg_maxind; + narg_maxind = 0; /* need to recalculate this */ + } + else + moreargs = garglist && garglist != list->next; + + /* "on format reuse the value of n shall refer to the nth argument + operand following the highest numbered argument operand consumed + by the previous use of the format operand." */ + /* This mess is to handle combining numbered and unnumbered conversion + specifiers. */ + if (moreargs && narg_argc != -1) + { + /* If we decide to treat numbered and unnumbered specifiers with + different counters. */ + if (garglist == 0 && orig_arglist != 0) + moreargs = 0; + /* I don't like this -- POSIX says "previous conversion specification + that consumed an argument", not "highest-numbered argument + processed" -- but this is what coreutils printf seems to do. */ + narg_seqind = narg_base; + /* The second clause will be true if we processed the last + argument (not necessarily all arguments). */ + if (narg_seqind >= narg_argc || (narg_base + 1) >= narg_argc) + moreargs = 0; + } } - while (garglist && garglist != list->next); + while (moreargs); if (conversion_error) retval = EXECUTION_FAILURE; @@ -1346,13 +1521,25 @@ mklong (char *str, char *modifiers, size_t mlen) static inline char * getarg (void) { + if (narg_argc != -1) + return narg_arg; + return (garglist ? garglist->word->word : 0); } static inline void advancearg (void) { - garglist = garglist->next; + if (narg_argc != -1) + { +#if 0 + /* see if we need to manage narg_seqind here or in printf_builtin */ + if (narg_numind < narg_argc) + narg_numind++; +#endif + } + else + garglist = garglist->next; } static int @@ -1404,15 +1591,19 @@ chk_converror (char *s, char *ep) } /* Don't call getintmax here because it may consume an argument on error, and - we call this to get field width/precision arguments. */ + we call this to get field width/precision arguments. This is only called + by getstar() to get field width/precision values from arguments. It does + not call getarg() and it does not advance the argument with advancearg. */ static int -getint (int overflow_retval) +getint (int numberedconv, int overflow_retval) { intmax_t ret; char *ep, *arg; int overflow; - arg = getarg (); + /* XXX - check here that narg_numind < narg_argc and return null in that case? */ + arg = (narg_argc != -1) ? (numberedconv ? narg_argv[narg_numind] : narg_argv[narg_seqind]) + : (garglist ? garglist->word->word : 0); if (arg == 0) return (0); @@ -1427,10 +1618,63 @@ getint (int overflow_retval) chk_converror (arg, ep); - advancearg (); return (overflow ? overflow_retval : (int)ret); } +static int +getstar (char **fmtp, int overflow_retval) +{ + int ret, numconv; + char *ep, **fp; + size_t l, ind; + + fp = fmtp; + + numconv = 0; + ep = *fp; + l = DIGIT (**fp) ? strspn (ep, DIGITS) : 0; + if (l > 0 && ep[l] == '$') + { + if (narg_argc == -1) + return overflow_retval; + ind = decodeint (fp, 1, -1); + if (**fp == '$') + { + ep = *fp + 1; + fp = &ep; + } + *fmtp = *fp; + ind += narg_base; + if (ind > 0 && ind <= narg_argc) /* can't have 0-based indices */ + narg_numind = ind; + else + return overflow_retval; + numconv = 1; + if (narg_numind > narg_maxind) + narg_maxind = narg_numind; + } + else if (narg_argc != -1) + { + if (narg_convwarned == 0) + { + builtin_warning ("%s", _("should not mix numbered and unnumbered conversions")); + narg_convwarned = 1; + } + /* We manage the sequential index here and in printf_builtin */ + if (narg_seqind < narg_argc) + ++narg_seqind; + if (narg_seqind > narg_maxind) + narg_maxind = narg_seqind; + } + + ret = getint (numconv, overflow_retval); + + if (narg_argc == -1) + advancearg (); + + return ret; +} + static intmax_t getintmax (void) { diff --git a/doc/bash.0 b/doc/bash.0 index da4d7d8f..1549badb 100644 --- a/doc/bash.0 +++ b/doc/bash.0 @@ -1689,6 +1689,9 @@ PPAARRAAMMEETTEERRSS The "+=" operator appends to an array variable when assigning using the compound assignment syntax; see PPAARRAAMMEETTEERRSS above. + If one of the word expansions in a compound array assignment unsets the + variable, the results are unspecified. + An array element is referenced using ${_n_a_m_e[_s_u_b_s_c_r_i_p_t]}. The braces are required to avoid conflicts with pathname expansion. If _s_u_b_s_c_r_i_p_t is @@ or **, the word expands to all members of _n_a_m_e, unless noted in the @@ -1899,7 +1902,7 @@ EEXXPPAANNSSIIOONN _p_a_r_a_m_e_t_e_r is a positional parameter with more than one digit, or when _p_a_r_a_m_e_t_e_r is followed by a character which is not to be interpreted as part of its name. The _p_a_r_a_m_e_t_e_r is a shell parameter as described - above PPAARRAAMMEETTEERRSS) or an array reference (AArrrraayyss). + above (PPAARRAAMMEETTEERRSS) or an array reference (AArrrraayyss). If the first character of _p_a_r_a_m_e_t_e_r is an exclamation point (!!), and _p_a_r_a_m_e_t_e_r is not a _n_a_m_e_r_e_f, it introduces a level of indirection. BBaasshh @@ -3729,6 +3732,7 @@ RREEAADDLLIINNEE form sseett _v_a_r_i_a_b_l_e_-_n_a_m_e _v_a_l_u_e + or using the bbiinndd builtin command (see SSHHEELLLL BBUUIILLTTIINN CCOOMMMMAANNDDSS below). Except where noted, rreeaaddlliinnee variables can take the values OOnn or OOffff @@ -4829,7 +4833,7 @@ RREEAADDLLIINNEE fined, programmable completion performs rreeaaddlliinnee's default completion. The options supplied to ccoommpplleettee and ccoommppoopptt can control how rreeaaddlliinnee - treats the completions. For instance, the _-_o _f_u_l_l_q_u_o_t_e option tells + treats the completions. For instance, the --oo ffuullllqquuoottee option tells rreeaaddlliinnee to quote the matches as if they were filenames. See the de- scription of ccoommpplleettee below for details. @@ -5745,8 +5749,8 @@ SSHHEELLLL BBUUIILLTTIINN CCOOMMMMAANNDDSS directories in which to search for _f_i_l_e_n_a_m_e. The default for BBAASSHH__LLOOAADDAABBLLEESS__PPAATTHH is system-dependent, and may include "." to force a search of the current directory. The --dd option will - delete a builtin previously loaded with --ff. If _-_s is used with - _-_f, the new builtin becomes a POSIX special builtin. + delete a builtin previously loaded with --ff. If --ss is used with + --ff, the new builtin becomes a POSIX special builtin. If no options are supplied and a _n_a_m_e is not a shell builtin, eennaabbllee will attempt to load _n_a_m_e from a shared object named @@ -6164,7 +6168,7 @@ SSHHEELLLL BBUUIILLTTIINN CCOOMMMMAANNDDSS last. If the top element of the directory stack is modified, and the - _-_n option was not supplied, ppooppdd uses the ccdd builtin to change + --nn option was not supplied, ppooppdd uses the ccdd builtin to change to the directory at the top of the stack. If the ccdd fails, ppooppdd returns a non-zero value. @@ -6232,12 +6236,27 @@ SSHHEELLLL BBUUIILLTTIINN CCOOMMMMAANNDDSS is the numeric value of the following character, using the cur- rent locale. - The _f_o_r_m_a_t is reused as necessary to consume all of the _a_r_g_u_- + Format specifiers may apply to the _nth argument rather than the + next sequential argument. In this case, the '%' in the format + specifier is replaced by the sequence "%_n$", where _n is a deci- + mal integer greater than 0, giving the argument number to use as + the operand. The format string should not mix numbered and un- + numbered argument specifiers, though this is allowed. Unnum- + bered argument specifiers always refer to the next argument fol- + lowing the last argument consumed by an unnumbered specifier; + numbered argument specifiers refer to absolute positions in the + argument list. + + The _f_o_r_m_a_t is reused as necessary to consume all of the _a_r_g_u_- _m_e_n_t_s. If the _f_o_r_m_a_t requires more _a_r_g_u_m_e_n_t_s than are supplied, - the extra format specifications behave as if a zero value or - null string, as appropriate, had been supplied. The return - value is zero on success, non-zero if an invalid option is sup- - plied or a write or assignment error occurs. + the extra format specifications behave as if a zero value or + null string, as appropriate, had been supplied. If _f_o_r_m_a_t is + reused, a numbered argument specifier "%_n$" refers to the _nth + argument following the highest numbered argument consumed by the + previous use of _f_o_r_m_a_t. + + The return value is zero on success, non-zero if an invalid op- + tion is supplied or a write or assignment error occurs. ppuusshhdd [--nn] [+_n] [-_n] ppuusshhdd [--nn] [_d_i_r] @@ -7555,4 +7574,4 @@ BBUUGGSS Array variables may not (yet) be exported. -GNU Bash 5.3 2025 October 6 _B_A_S_H(1) +GNU Bash 5.3 2025 December 2 _B_A_S_H(1) diff --git a/doc/bash.1 b/doc/bash.1 index afe320ee..4554754e 100644 --- a/doc/bash.1 +++ b/doc/bash.1 @@ -5,7 +5,7 @@ .\" Case Western Reserve University .\" chet.ramey@case.edu .\" -.\" Last Change: Mon Nov 17 11:37:04 EST 2025 +.\" Last Change: Tue Dec 2 16:43:36 EST 2025 .\" .\" For bash_builtins, strip all but "SHELL BUILTIN COMMANDS" section .\" For rbash, strip all but "RESTRICTED SHELL" section @@ -22,7 +22,7 @@ .ds zX \" empty .if \n(zZ=1 .ig zZ .if \n(zY=1 .ig zY -.TH BASH 1 "2025 November 17" "GNU Bash 5.3" +.TH BASH 1 "2025 December 2" "GNU Bash 5.3" .\" .ie \n(.g \{\ .ds ' \(aq @@ -11148,10 +11148,28 @@ except that a leading plus or minus sign is allowed, and if the leading character is a single or double quote, the value is the numeric value of the following character, using the current locale. .IP +Format specifiers may apply to the \fIn\fPth argument rather than the next +sequential argument. +In this case, the '%' in the format specifier is replaced by the +sequence +.Q %\fIn\fP$ , +where \fIn\fP is a decimal integer greater than 0, +giving the argument number to use as the operand. +The format string should not mix numbered and unnumbered argument specifiers, +though this is allowed. +Unnumbered argument specifiers always refer to the next argument following +the last argument consumed by an unnumbered specifier; numbered argument +specifiers refer to absolute positions in the argument list. +.IP The \fIformat\fP is reused as necessary to consume all of the \fIarguments\fP. If the \fIformat\fP requires more \fIarguments\fP than are supplied, the extra format specifications behave as if a zero value or null string, as appropriate, had been supplied. +If \fIformat\fP is reused, a numbered argument specifier +.Q %\fIn\fP$ +refers to the \fIn\fPth argument following the highest numbered argument +consumed by the previous use of \fIformat\fP. +.IP The return value is zero on success, non-zero if an invalid option is supplied or a write or assignment error occurs. diff --git a/doc/bash.html b/doc/bash.html index 46a6da12..14e4e194 100644 --- a/doc/bash.html +++ b/doc/bash.html @@ -1,5 +1,5 @@ - + @@ -3736,6 +3736,10 @@ an index of −1 references the last element.
assigning using the compound assignment syntax; see PARAMETERS above. +If one of the +word expansions in a compound array assignment unsets the +variable, the results are unspecified.
+An array element is referenced using ${name[subscript]}. The braces are required to avoid conflicts with pathname @@ -4056,7 +4060,7 @@ required when parameter is a positional parameter with more than one digit, or when parameter is followed by a character which is not to be interpreted as part of its name. The parameter is a shell parameter -as described above PARAMETERS) or an array reference +as described above (PARAMETERS) or an array reference (Arrays).
If the first @@ -7793,9 +7797,9 @@ with a statement of the form
set variable−name value
-or using the bind builtin -command (see SHELL BUILTIN COMMANDS -below).
+or using the +bind builtin command (see SHELL BUILTIN +COMMANDS below).
Except where noted, readline variables can take the values @@ -9875,7 +9879,7 @@ completion.
The options supplied to complete and compopt can control how readline treats the completions. For instance, -the −o fullquote option tells readline +the −o fullquote option tells readline to quote the matches as if they were filenames. See the description of complete below for details.
@@ -10537,9 +10541,10 @@ interpretation.All builtins
except :, true, false, echo, and
-test/[ accept --help as a special
-option. If --help is supplied, these builtins output
-a help message and exit with a status of 0.
+test/[ accept −−help as a
+special option. If −−help is supplied,
+these builtins output a help message and exit with a status
+of 0.
: [arguments]
No effect; the command does @@ -12119,8 +12124,8 @@ The default for BASH_LOADABLES_PATH is system-dependent, and may include “.” to force a search of the current directory. The −d option will delete a builtin previously loaded with -−f. If −s is used with -−f, the new builtin becomes a +−f. If −s is used with +−f, the new builtin becomes a POSIX special builtin.
If no options @@ -13011,7 +13016,7 @@ directory, “popd −1” the next to last.
If the top element of the directory stack is modified, and the -−n option was not supplied, popd uses +−n option was not supplied, popd uses the cd builtin to change to the directory at the top of the stack. If the cd fails, popd returns a non-zero value.
@@ -13131,14 +13136,33 @@ the leading character is a single or double quote, the value is the numeric value of the following character, using the current locale. +Format +specifiers may apply to the nth argument rather than +the next sequential argument. In this case, the +’%’ in the format specifier is replaced by the +sequence “%n$”, where n is a +decimal integer greater than 0, giving the argument number +to use as the operand. The format string should not mix +numbered and unnumbered argument specifiers, though this is +allowed. Unnumbered argument specifiers always refer to the +next argument following the last argument consumed by an +unnumbered specifier; numbered argument specifiers refer to +absolute positions in the argument list.
+The format is reused as necessary to consume all of the arguments. If the format requires more arguments than are supplied, the extra format specifications behave as if a zero value or null string, as -appropriate, had been supplied. The return value is zero on -success, non-zero if an invalid option is supplied or a -write or assignment error occurs.
+appropriate, had been supplied. If format is reused, +a numbered argument specifier “%n$” +refers to the nth argument following the highest +numbered argument consumed by the previous use of +format. + +The return +value is zero on success, non-zero if an invalid option is +supplied or a write or assignment error occurs.
pushd [−n]
[+n] [−n]
diff --git a/doc/bash.info b/doc/bash.info
index 17059200..3143f1c2 100644
--- a/doc/bash.info
+++ b/doc/bash.info
@@ -1,9 +1,9 @@
This is bash.info, produced by makeinfo version 7.2 from bashref.texi.
This text is a brief description of the features that are present in the
-Bash shell (version 5.3, 24 September 2025).
+Bash shell (version 5.3, 2 December 2025).
- This is Edition 5.3, last updated 24 September 2025, of ‘The GNU Bash
+ This is Edition 5.3, last updated 2 December 2025, of ‘The GNU Bash
Reference Manual’, for ‘Bash’, Version 5.3.
Copyright © 1988-2025 Free Software Foundation, Inc.
@@ -26,10 +26,10 @@ Bash Features
*************
This text is a brief description of the features that are present in the
-Bash shell (version 5.3, 24 September 2025). The Bash home page is
+Bash shell (version 5.3, 2 December 2025). The Bash home page is