newline, among other things.
From https://savannah.gnu.org/patch/?10517
+ 4/29
+ ----
+builtins/evalstring.c
+ - parse_string: only run the top-level unwind-protects if we're
+ actually going to be calling jump_to_top_level(); otherwise let
+ xparse_dolparen take care of it
+ From a report by Александр Ушаков <aushakov@astralinux.ru>
+
+ 5/1
+ ---
+lib/sh/zread.c
+ - zungetc: rework to use a local 16-byte buffer so we can push back
+ multiple characters whether we use read or zread
+ - zread/zreadretry/zreadintr/zreadc/zreadcintr/zreadn: changed to use
+ zpopbuf to check whether we have pushed back bytes
+ - zreset,zsyncfd: reset the pushback buffer indices
+
+builtins/read.def
+ - read_mbchar: handle the delimiter being part of an invalid multibyte
+ character, not just the byte that makes the multibyte character
+ invalid: keep track of where the delimiter char is in the buffer and
+ use zungetc to push back that character and everything we read
+ after it so subsequent buffered (zread) or unbuffered (read) reads
+ will return them
if (current_token == yacc_EOF || current_token == shell_eof_token)
{
- if (current_token == shell_eof_token)
+ /* check for EOFTOKEN out of paranoia */
+ if ((parser_state & PST_EOFTOKEN) && (current_token == shell_eof_token))
rewind_input_string ();
break;
}
us, after doing cleanup */
if (should_jump_to_top_level)
{
- if (parse_and_execute_level == 0)
- top_level_cleanup ();
if (code == DISCARD)
return -DISCARD;
+ if (parse_and_execute_level == 0)
+ top_level_cleanup ();
jump_to_top_level (code);
}
read_mbchar (int fd, char *string, int ind, int ch, int delim, int unbuffered)
{
char mbchar[MB_LEN_MAX + 1];
- int i, n, r;
+ int i, n, r, delim_ind;
char c;
size_t ret;
mbstate_t ps, ps_back;
memset (&ps, '\0', sizeof (mbstate_t));
memset (&ps_back, '\0', sizeof (mbstate_t));
-
+
+ delim_ind = 0;
mbchar[0] = ch;
i = 1;
for (n = 0; n <= MB_LEN_MAX; n++)
r = zreadc (fd, &c);
if (r <= 0)
goto mbchar_return;
+ if ((unsigned char)c == delim)
+ delim_ind = i;
mbchar[i++] = c;
continue;
}
else if (ret == (size_t)-1)
{
- /* If we read (i > 1) a delimiter character (c == delimiter)
- that makes this an invalid multibyte character, we can't just
- add it to the input string and treat it as a byte.
- We need to push it back so a subsequent zread will pick it up. */
- if (i > 1 && (unsigned char)c == delim)
+ /* If we read (i > 1) a delimiter character (delim_ind >= 1)
+ that is a part of this invalid multibyte character, we can't
+ just add it to the input string and treat it as a byte.
+ We need to push it and everything we read after it back so a
+ subsequent zread will pick it up. */
+ if (i > 1 && delim_ind >= 1)
{
- zungetc ((unsigned char)c);
- i--;
+ size_t j;
+ for (j = delim_ind; j < i; j++)
+ zungetc ((unsigned char)mbchar[j]);
+ i = delim_ind;
}
break; /* invalid multibyte character */
}
/* Define if you have the snprintf function. */
#undef HAVE_SNPRINTF
+/* Define if you have the statfs function. */
+#undef HAVE_STATFS
+
/* Define if you have the strcasecmp function. */
#undef HAVE_STRCASECMP
#! /bin/sh
-# From configure.ac for Bash 5.3, version 5.077.
+# From configure.ac for Bash 5.3, version 5.078.
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.72 for bash 5.3-rc1.
#
then :
printf "%s\n" "#define HAVE_SETITIMER 1" >>confdefs.h
+fi
+ac_fn_c_check_func "$LINENO" "statfs" "ac_cv_func_statfs"
+if test "x$ac_cv_func_statfs" = xyes
+then :
+ printf "%s\n" "#define HAVE_STATFS 1" >>confdefs.h
+
fi
ac_fn_c_check_func "$LINENO" "tcgetpgrp" "ac_cv_func_tcgetpgrp"
if test "x$ac_cv_func_tcgetpgrp" = xyes
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-AC_REVISION([for Bash 5.3, version 5.077])dnl
+AC_REVISION([for Bash 5.3, version 5.078])dnl
define(bashvers, 5.3)
define(relstatus, rc1)
gethostname getpagesize getpeername getrandom getrlimit \
getrusage gettimeofday kill killpg lstat nanosleep \
pselect readlink \
- select setdtablesize setitimer tcgetpgrp uname ulimit waitpid)
+ select setdtablesize setitimer statfs \
+ tcgetpgrp uname ulimit waitpid)
AC_REPLACE_FUNCS(rename)
dnl checks for c library functions
value. The current value is usually an integer constant, but may be an
expression. When "+=" is applied to an array variable using compound
assignment (see A\bAr\brr\bra\bay\bys\bs below), the variable's value is not unset (as it
- is when using and new values are appended to the array beginning at one
- greater than the array's maximum index (for indexed arrays) or added as
- additional key-value pairs in an associative array. When applied to a
- string-valued variable, _\bv_\ba_\bl_\bu_\be is expanded and appended to the vari-
- able's value.
+ is when using "="), and new values are appended to the array beginning
+ at one greater than the array's maximum index (for indexed arrays) or
+ added as additional key-value pairs in an associative array. When ap-
+ plied to a string-valued variable, _\bv_\ba_\bl_\bu_\be is expanded and appended to
+ the variable's value.
A variable can be assigned the _\bn_\ba_\bm_\be_\br_\be_\bf attribute using the -\b-n\bn option to
the d\bde\bec\bcl\bla\bar\bre\be or l\blo\boc\bca\bal\bl builtin commands (see the descriptions of d\bde\bec\bcl\bla\bar\bre\be
below),
the variable's value is not unset
(as it is when using
-.@ = ),
+.Q = ),
and new values are appended to the array
beginning at one greater than the array's maximum index (for indexed arrays)
or added as additional key\-value pairs in an associative array.
Interactive shells will notify the user of completed jobs while sourcing a
script.
Newer versions defer notification until script execution completes.
+@ignore
+@item
+Bash will not try to execute a shell function whose name contains a slash.
+Previous versions disallowed this in @sc{posix} mode but allowed it by
+default.
+@end ignore
@end itemize
@end table
builtin_is_special = 1;
}
if (builtin == 0)
+#if 0 /*TAG bash-5.4 rob@landley.net 5/1/2025 */
+ func = ((shell_compatibility_level <= 52 && posixly_correct == 0) || absolute_program (words->word->word) == 0) ? find_function (words->word->word) : 0;
+#else
func = (posixly_correct == 0 || absolute_program (words->word->word) == 0) ? find_function (words->word->word) : 0;
+#endif
}
/* What happens in posix mode when an assignment preceding a command name
int zungetc (int);
-/* Provide one character of pushback whether we are using read or zread. */
-static int zpushedchar = -1;
+/* Provide 16 bytes of pushback whether we are using read or zread. Only used
+ by the read builtin when reading invalid multibyte characters. */
+#define ZPUSHSIZE 16
+
+static size_t zpushind, zpopind;
+static unsigned char zpushbuf[ZPUSHSIZE];
+static unsigned char zbufchar;
+
+static inline int
+zbufpop(unsigned char *cp)
+{
+ if (zpushind == zpopind)
+ return (0);
+ *cp = zpushbuf[zpopind++];
+ if (zpopind == zpushind)
+ zpopind = zpushind = 0; /* reset, buffer empty */
+ return 1;
+}
+
+static inline int
+zbufpush(int c)
+{
+ if (zpushind == ZPUSHSIZE - 1)
+ return 0;
+ zpushbuf[zpushind++] = c;
+ return 1;
+}
+
+/* Add C to the pushback buffer. Can't push back EOF */
+int
+zungetc (int c)
+{
+ zbufpush (c);
+ return c;
+}
/* Read LEN bytes from FD into BUF. Retry the read on EINTR. Any other
error causes the loop to break. */
check_signals (); /* check for signals before a blocking read */
- /* If we pushed a char back, return it immediately */
- if (zpushedchar != -1)
+ /* If we pushed chars back, return the oldest one immediately */
+ if (zbufpop (&zbufchar))
{
- *buf = (unsigned char)zpushedchar;
- zpushedchar = -1;
+ *buf = zbufchar;
return 1;
}
ssize_t r;
int nintr;
- /* If we pushed a char back, return it immediately */
- if (zpushedchar != -1)
+ /* If we pushed chars back, return the oldest one immediately */
+ if (zbufpop (&zbufchar))
{
- *buf = (unsigned char)zpushedchar;
- zpushedchar = -1;
+ *buf = zbufchar;
return 1;
}
{
check_signals ();
- /* If we pushed a char back, return it immediately */
- if (zpushedchar != -1)
- {
- *buf = (unsigned char)zpushedchar;
- zpushedchar = -1;
- return 1;
- }
-
+ /* If we pushed chars back, return the oldest one immediately */
+ if (zbufpop (&zbufchar))
+ {
+ *buf = zbufchar;
+ return 1;
+ }
+
return (read (fd, buf, len));
}
{
ssize_t nr;
- /* If we pushed a char back, return it immediately */
- if (zpushedchar != -1 && cp)
- {
- *cp = (unsigned char)zpushedchar;
- zpushedchar = -1;
- return 1;
- }
-
+ /* If we pushed chars back, return the oldest one immediately */
+ if (cp && zbufpop (&zbufchar))
+ {
+ *cp = zbufchar;
+ return 1;
+ }
+
if (lind == lused || lused == 0)
{
nr = zread (fd, lbuf, sizeof (lbuf));
{
ssize_t nr;
- /* If we pushed a char back, return it immediately */
- if (zpushedchar != -1 && cp)
- {
- *cp = (unsigned char)zpushedchar;
- zpushedchar = -1;
- return 1;
+ /* If we pushed chars back, return the oldest one immediately */
+ if (cp && zbufpop (&zbufchar))
+ {
+ *cp = zbufchar;
+ return 1;
}
if (lind == lused || lused == 0)
{
ssize_t nr;
- if (zpushedchar != -1 && cp)
- {
- *cp = zpushedchar;
- zpushedchar = -1;
- return 1;
+ /* If we pushed chars back, return the oldest one immediately */
+ if (cp && zbufpop (&zbufchar))
+ {
+ *cp = zbufchar;
+ return 1;
}
if (lind == lused || lused == 0)
return 1;
}
-int
-zungetc (int c)
-{
- if (zpushedchar == -1)
- {
- zpushedchar = c;
- return c;
- }
-
- if (c == EOF || lind == 0)
- return (EOF);
- lbuf[--lind] = c; /* XXX */
- return c;
-}
-
void
zreset (void)
{
lind = lused = 0;
+ zpushind = zpopind = 0;
}
/* Sync the seek pointer for FD so that the kernel's idea of the last char
r = lseek (fd, -off, SEEK_CUR);
if (r != -1)
- lused = lind = 0;
+ {
+ lused = lind = 0;
+ zpushind = zpopind = 0;
+ }
}