mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-06-27 07:43:07 +02:00
commit bash-20190220 snapshot
This commit is contained in:
@@ -5317,3 +5317,44 @@ jobs.c
|
||||
an interactive shell reported by Grisha Levit
|
||||
<grishalevit@gmail.com>
|
||||
|
||||
2/19
|
||||
----
|
||||
|
||||
jobs.c
|
||||
- end_job_control: if the setpgid(0, ...) succeeds, reset the value of
|
||||
shell_pgrp. Fixes pgrp mismatch after failed exec in an interactive
|
||||
login shell reported by Grisha Levit <grishalevit@gmail.com>
|
||||
|
||||
2/20
|
||||
----
|
||||
bashhist.c
|
||||
- pre_process_line: save history_length before calling history_expand,
|
||||
and after possibly decrementing history_length, just restore the old
|
||||
value instead of incrementing it. Fixes bug reported by
|
||||
Michael Albinus <michael.albinus@gmx.de>
|
||||
- bash_add_history: don't bother calling really_add_history if the
|
||||
history is stifled and the max number of entries is 0
|
||||
|
||||
aclocal.m4,configure.ac,m4/*.m4
|
||||
- replace the old set of gettext m4 macros with the latest m4 files
|
||||
from the gnulib and gettext distributions
|
||||
|
||||
2/21
|
||||
----
|
||||
builtins/cd.def
|
||||
- bindpwd: initialize canon_failed to 0 to prevent `cd -e' from always
|
||||
failing
|
||||
|
||||
command.h
|
||||
- W_EXPANDRHS: new flag, set when expanding WORD in ${paramOPword}
|
||||
|
||||
subst.c
|
||||
- expand_string_for_rhs: set W_EXPANDRHS in word to be expanded
|
||||
|
||||
subst.c
|
||||
- expand_word_internal: when encountering a single or double quoted
|
||||
string that expands to nothing, add a CTLNUL if the W_EXPANDRHS
|
||||
flag is set and the word isn't quoted, indicating that the word
|
||||
will eventually be split and we need to preserve the null to
|
||||
produce an empty word. From a discussion on bug-bash started by
|
||||
sunnycemetery@gmail.com
|
||||
|
||||
@@ -502,6 +502,7 @@ m4/nls.m4 f
|
||||
m4/po.m4 f
|
||||
m4/printf-posix.m4 f
|
||||
m4/progtest.m4 f
|
||||
m4/pthread_rwlock_rdlock.m4 f
|
||||
m4/size_max.m4 f
|
||||
m4/stdint_h.m4 f
|
||||
m4/threadlib.m4 f
|
||||
|
||||
+7
-1
@@ -560,15 +560,18 @@ pre_process_line (line, print_changes, addit)
|
||||
add that line to the history if ADDIT is non-zero. */
|
||||
if (!history_expansion_inhibited && history_expansion && history_expansion_p (line))
|
||||
{
|
||||
int old_len;
|
||||
|
||||
/* If we are expanding the second or later line of a multi-line
|
||||
command, decrease history_length so references to history expansions
|
||||
in these lines refer to the previous history entry and not the
|
||||
current command. */
|
||||
old_len = history_length;
|
||||
if (history_length > 0 && command_oriented_history && current_command_first_line_saved && current_command_line_count > 1)
|
||||
history_length--;
|
||||
expanded = history_expand (line, &history_value);
|
||||
if (history_length >= 0 && command_oriented_history && current_command_first_line_saved && current_command_line_count > 1)
|
||||
history_length++;
|
||||
history_length = old_len;
|
||||
|
||||
if (expanded)
|
||||
{
|
||||
@@ -908,6 +911,9 @@ bash_add_history (line)
|
||||
}
|
||||
}
|
||||
|
||||
if (add_it && history_is_stifled() && history_length == 0 && history_length == history_max_entries)
|
||||
add_it = 0;
|
||||
|
||||
if (add_it)
|
||||
really_add_history (line);
|
||||
|
||||
|
||||
@@ -149,6 +149,7 @@ bindpwd (no_symlinks)
|
||||
#undef tcwd
|
||||
|
||||
/* If canonicalization fails, reset dirname to the_current_working_directory */
|
||||
canon_failed = 0;
|
||||
if (dirname == 0)
|
||||
{
|
||||
canon_failed = 1;
|
||||
|
||||
@@ -87,7 +87,7 @@ enum command_type { cm_for, cm_case, cm_while, cm_if, cm_simple, cm_select,
|
||||
#define W_ASSIGNRHS 0x000800 /* Word is rhs of an assignment statement */
|
||||
#define W_NOTILDE 0x001000 /* Don't perform tilde expansion on this word */
|
||||
#define W_ITILDE 0x002000 /* Internal flag for word expansion */
|
||||
#define W_NOEXPAND 0x004000 /* Don't expand at all -- do quote removal */
|
||||
#define W_EXPANDRHS 0x004000 /* Expanding word in ${paramOPword} */
|
||||
#define W_COMPASSIGN 0x008000 /* Compound assignment */
|
||||
#define W_ASSNBLTIN 0x010000 /* word is a builtin command that takes assignments */
|
||||
#define W_ASSIGNARG 0x020000 /* word is assignment argument to command */
|
||||
@@ -111,6 +111,7 @@ enum command_type { cm_for, cm_case, cm_while, cm_if, cm_simple, cm_select,
|
||||
#define PF_NOSPLIT2 0x04 /* same as W_NOSPLIT2 */
|
||||
#define PF_ASSIGNRHS 0x08 /* same as W_ASSIGNRHS */
|
||||
#define PF_COMPLETE 0x10 /* same as W_COMPLETE, sets SX_COMPLETE */
|
||||
#define PF_EXPANDRHS 0x20 /* same as W_EXPANDRHS */
|
||||
|
||||
/* Possible values for subshell_environment */
|
||||
#define SUBSHELL_ASYNC 0x01 /* subshell caused by `command &' */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#! /bin/sh
|
||||
# From configure.ac for Bash 5.0, version 5.007.
|
||||
# From configure.ac for Bash 5.0, version 5.008.
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.69 for bash 5.0-maint.
|
||||
#
|
||||
@@ -6242,6 +6242,11 @@ fi
|
||||
|
||||
|
||||
|
||||
# pthread_rwlock_rdlock.m4 serial 2
|
||||
|
||||
|
||||
|
||||
|
||||
# size_max.m4 serial 11
|
||||
|
||||
|
||||
@@ -9642,7 +9647,155 @@ $as_echo "#define HAVE_PTHREAD_RWLOCK 1" >>confdefs.h
|
||||
fi
|
||||
|
||||
if $has_rwlock; then
|
||||
gl_PTHREAD_RWLOCK_RDLOCK_PREFER_WRITER
|
||||
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthread_rwlock_rdlock prefers a writer to a reader" >&5
|
||||
$as_echo_n "checking whether pthread_rwlock_rdlock prefers a writer to a reader... " >&6; }
|
||||
if ${gl_cv_pthread_rwlock_rdlock_prefer_writer+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
save_LIBS="$LIBS"
|
||||
LIBS="$LIBS $LIBMULTITHREAD"
|
||||
if test "$cross_compiling" = yes; then :
|
||||
gl_cv_pthread_rwlock_rdlock_prefer_writer="guessing yes"
|
||||
else
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define SUCCEED() exit (0)
|
||||
#define FAILURE() exit (1)
|
||||
#define UNEXPECTED(n) (exit (10 + (n)))
|
||||
|
||||
/* The main thread creates the waiting writer and the requesting reader threads
|
||||
in the default way; this guarantees that they have the same priority.
|
||||
We can reuse the main thread as first reader thread. */
|
||||
|
||||
static pthread_rwlock_t lock;
|
||||
static pthread_t reader1;
|
||||
static pthread_t writer;
|
||||
static pthread_t reader2;
|
||||
static pthread_t timer;
|
||||
/* Used to pass control from writer to reader2 and from reader2 to timer,
|
||||
as in a relay race.
|
||||
Passing control from one running thread to another running thread
|
||||
is most likely faster than to create the second thread. */
|
||||
static pthread_mutex_t baton;
|
||||
|
||||
static void *
|
||||
timer_func (void *ignored)
|
||||
{
|
||||
/* Step 13 (can be before or after step 12):
|
||||
The timer thread takes the baton, then waits a moment to make sure
|
||||
it can tell whether the second reader thread is blocked at step 12. */
|
||||
if (pthread_mutex_lock (&baton))
|
||||
UNEXPECTED (13);
|
||||
usleep (100000);
|
||||
/* By the time we get here, it's clear that the second reader thread is
|
||||
blocked at step 12. This is the desired behaviour. */
|
||||
SUCCEED ();
|
||||
}
|
||||
|
||||
static void *
|
||||
reader2_func (void *ignored)
|
||||
{
|
||||
int err;
|
||||
|
||||
/* Step 8 (can be before or after step 7):
|
||||
The second reader thread takes the baton, then waits a moment to make sure
|
||||
the writer thread has reached step 7. */
|
||||
if (pthread_mutex_lock (&baton))
|
||||
UNEXPECTED (8);
|
||||
usleep (100000);
|
||||
/* Step 9: The second reader thread requests the lock. */
|
||||
err = pthread_rwlock_tryrdlock (&lock);
|
||||
if (err == 0)
|
||||
FAILURE ();
|
||||
else if (err != EBUSY)
|
||||
UNEXPECTED (9);
|
||||
/* Step 10: Launch a timer, to test whether the next call blocks. */
|
||||
if (pthread_create (&timer, NULL, timer_func, NULL))
|
||||
UNEXPECTED (10);
|
||||
/* Step 11: Release the baton. */
|
||||
if (pthread_mutex_unlock (&baton))
|
||||
UNEXPECTED (11);
|
||||
/* Step 12: The second reader thread requests the lock. */
|
||||
err = pthread_rwlock_rdlock (&lock);
|
||||
if (err == 0)
|
||||
FAILURE ();
|
||||
else
|
||||
UNEXPECTED (12);
|
||||
}
|
||||
|
||||
static void *
|
||||
writer_func (void *ignored)
|
||||
{
|
||||
/* Step 4: Take the baton, so that the second reader thread does not go ahead
|
||||
too early. */
|
||||
if (pthread_mutex_lock (&baton))
|
||||
UNEXPECTED (4);
|
||||
/* Step 5: Create the second reader thread. */
|
||||
if (pthread_create (&reader2, NULL, reader2_func, NULL))
|
||||
UNEXPECTED (5);
|
||||
/* Step 6: Release the baton. */
|
||||
if (pthread_mutex_unlock (&baton))
|
||||
UNEXPECTED (6);
|
||||
/* Step 7: The writer thread requests the lock. */
|
||||
if (pthread_rwlock_wrlock (&lock))
|
||||
UNEXPECTED (7);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
reader1 = pthread_self ();
|
||||
|
||||
/* Step 1: The main thread initializes the lock and the baton. */
|
||||
if (pthread_rwlock_init (&lock, NULL))
|
||||
UNEXPECTED (1);
|
||||
if (pthread_mutex_init (&baton, NULL))
|
||||
UNEXPECTED (1);
|
||||
/* Step 2: The main thread acquires the lock as a reader. */
|
||||
if (pthread_rwlock_rdlock (&lock))
|
||||
UNEXPECTED (2);
|
||||
/* Step 3: Create the writer thread. */
|
||||
if (pthread_create (&writer, NULL, writer_func, NULL))
|
||||
UNEXPECTED (3);
|
||||
/* Job done. Go to sleep. */
|
||||
for (;;)
|
||||
{
|
||||
sleep (1);
|
||||
}
|
||||
}
|
||||
|
||||
_ACEOF
|
||||
if ac_fn_c_try_run "$LINENO"; then :
|
||||
gl_cv_pthread_rwlock_rdlock_prefer_writer=yes
|
||||
else
|
||||
gl_cv_pthread_rwlock_rdlock_prefer_writer=no
|
||||
fi
|
||||
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
|
||||
conftest.$ac_objext conftest.beam conftest.$ac_ext
|
||||
fi
|
||||
|
||||
LIBS="$save_LIBS"
|
||||
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_pthread_rwlock_rdlock_prefer_writer" >&5
|
||||
$as_echo "$gl_cv_pthread_rwlock_rdlock_prefer_writer" >&6; }
|
||||
case "$gl_cv_pthread_rwlock_rdlock_prefer_writer" in
|
||||
*yes)
|
||||
|
||||
$as_echo "#define HAVE_PTHREAD_RWLOCK_RDLOCK_PREFER_WRITER 1" >>confdefs.h
|
||||
|
||||
;;
|
||||
esac
|
||||
|
||||
fi
|
||||
# glibc defines PTHREAD_MUTEX_RECURSIVE as enum, not as a macro.
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
|
||||
+2
-1
@@ -21,7 +21,7 @@ dnl Process this file with autoconf to produce a configure script.
|
||||
# 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.0, version 5.007])dnl
|
||||
AC_REVISION([for Bash 5.0, version 5.008])dnl
|
||||
|
||||
define(bashvers, 5.0)
|
||||
define(relstatus, maint)
|
||||
@@ -712,6 +712,7 @@ m4_include([m4/nls.m4])
|
||||
m4_include([m4/po.m4])
|
||||
m4_include([m4/printf-posix.m4])
|
||||
m4_include([m4/progtest.m4])
|
||||
m4_include([m4/pthread_rwlock_rdlock.m4])
|
||||
m4_include([m4/size_max.m4])
|
||||
m4_include([m4/stdint_h.m4])
|
||||
m4_include([m4/threadlib.m4])
|
||||
|
||||
+1
-1
@@ -7188,7 +7188,7 @@ is also accepted; the @var{subscript} is ignored.
|
||||
@noindent
|
||||
Associative arrays are created using
|
||||
@example
|
||||
declare -A @var{name}.
|
||||
declare -A @var{name}
|
||||
@end example
|
||||
|
||||
Attributes may be
|
||||
|
||||
@@ -4844,8 +4844,8 @@ end_job_control ()
|
||||
if (original_pgrp >= 0 && terminal_pgrp != original_pgrp)
|
||||
give_terminal_to (original_pgrp, 1);
|
||||
|
||||
if (original_pgrp >= 0)
|
||||
setpgid (0, original_pgrp);
|
||||
if (original_pgrp >= 0 && setpgid (0, original_pgrp) == 0)
|
||||
shell_pgrp = original_pgrp;
|
||||
}
|
||||
|
||||
/* Restart job control by closing shell tty and reinitializing. This is
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
# pthread_rwlock_rdlock.m4 serial 2
|
||||
dnl Copyright (C) 2017-2019 Free Software Foundation, Inc.
|
||||
dnl This file is free software; the Free Software Foundation
|
||||
dnl gives unlimited permission to copy and/or distribute it,
|
||||
dnl with or without modifications, as long as this notice is preserved.
|
||||
|
||||
dnl From Bruno Haible.
|
||||
dnl Inspired by
|
||||
dnl https://github.com/linux-test-project/ltp/blob/master/testcases/open_posix_testsuite/conformance/interfaces/pthread_rwlock_rdlock/2-2.c
|
||||
dnl by Intel Corporation.
|
||||
|
||||
dnl Test whether in a situation where
|
||||
dnl - an rwlock is taken by a reader and has a writer waiting,
|
||||
dnl - an additional reader requests the lock,
|
||||
dnl - the waiting writer and the requesting reader threads have the same
|
||||
dnl priority,
|
||||
dnl the requesting reader thread gets blocked, so that at some point the
|
||||
dnl waiting writer can acquire the lock.
|
||||
dnl Without such a guarantee, when there a N readers and each of the readers
|
||||
dnl spends more than 1/Nth of the time with the lock held, there is a high
|
||||
dnl probability that the waiting writer will not get the lock in a given finite
|
||||
dnl time, a phenomenon called "writer starvation".
|
||||
dnl Without such a guarantee, applications have a hard time avoiding writer
|
||||
dnl starvation.
|
||||
dnl
|
||||
dnl POSIX:2017 makes this requirement only for implementations that support TPS
|
||||
dnl (Thread Priority Scheduling) and only for the scheduling policies SCHED_FIFO
|
||||
dnl and SCHED_RR, see
|
||||
dnl http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_rwlock_rdlock.html
|
||||
dnl but this test verifies the guarantee regardless of TPS and regardless of
|
||||
dnl scheduling policy.
|
||||
dnl Glibc currently does not provide this guarantee, see
|
||||
dnl https://sourceware.org/bugzilla/show_bug.cgi?id=13701
|
||||
AC_DEFUN([gl_PTHREAD_RWLOCK_RDLOCK_PREFER_WRITER],
|
||||
[
|
||||
AC_REQUIRE([gl_THREADLIB_EARLY])
|
||||
AC_CACHE_CHECK([whether pthread_rwlock_rdlock prefers a writer to a reader],
|
||||
[gl_cv_pthread_rwlock_rdlock_prefer_writer],
|
||||
[save_LIBS="$LIBS"
|
||||
LIBS="$LIBS $LIBMULTITHREAD"
|
||||
AC_RUN_IFELSE(
|
||||
[AC_LANG_SOURCE([[
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define SUCCEED() exit (0)
|
||||
#define FAILURE() exit (1)
|
||||
#define UNEXPECTED(n) (exit (10 + (n)))
|
||||
|
||||
/* The main thread creates the waiting writer and the requesting reader threads
|
||||
in the default way; this guarantees that they have the same priority.
|
||||
We can reuse the main thread as first reader thread. */
|
||||
|
||||
static pthread_rwlock_t lock;
|
||||
static pthread_t reader1;
|
||||
static pthread_t writer;
|
||||
static pthread_t reader2;
|
||||
static pthread_t timer;
|
||||
/* Used to pass control from writer to reader2 and from reader2 to timer,
|
||||
as in a relay race.
|
||||
Passing control from one running thread to another running thread
|
||||
is most likely faster than to create the second thread. */
|
||||
static pthread_mutex_t baton;
|
||||
|
||||
static void *
|
||||
timer_func (void *ignored)
|
||||
{
|
||||
/* Step 13 (can be before or after step 12):
|
||||
The timer thread takes the baton, then waits a moment to make sure
|
||||
it can tell whether the second reader thread is blocked at step 12. */
|
||||
if (pthread_mutex_lock (&baton))
|
||||
UNEXPECTED (13);
|
||||
usleep (100000);
|
||||
/* By the time we get here, it's clear that the second reader thread is
|
||||
blocked at step 12. This is the desired behaviour. */
|
||||
SUCCEED ();
|
||||
}
|
||||
|
||||
static void *
|
||||
reader2_func (void *ignored)
|
||||
{
|
||||
int err;
|
||||
|
||||
/* Step 8 (can be before or after step 7):
|
||||
The second reader thread takes the baton, then waits a moment to make sure
|
||||
the writer thread has reached step 7. */
|
||||
if (pthread_mutex_lock (&baton))
|
||||
UNEXPECTED (8);
|
||||
usleep (100000);
|
||||
/* Step 9: The second reader thread requests the lock. */
|
||||
err = pthread_rwlock_tryrdlock (&lock);
|
||||
if (err == 0)
|
||||
FAILURE ();
|
||||
else if (err != EBUSY)
|
||||
UNEXPECTED (9);
|
||||
/* Step 10: Launch a timer, to test whether the next call blocks. */
|
||||
if (pthread_create (&timer, NULL, timer_func, NULL))
|
||||
UNEXPECTED (10);
|
||||
/* Step 11: Release the baton. */
|
||||
if (pthread_mutex_unlock (&baton))
|
||||
UNEXPECTED (11);
|
||||
/* Step 12: The second reader thread requests the lock. */
|
||||
err = pthread_rwlock_rdlock (&lock);
|
||||
if (err == 0)
|
||||
FAILURE ();
|
||||
else
|
||||
UNEXPECTED (12);
|
||||
}
|
||||
|
||||
static void *
|
||||
writer_func (void *ignored)
|
||||
{
|
||||
/* Step 4: Take the baton, so that the second reader thread does not go ahead
|
||||
too early. */
|
||||
if (pthread_mutex_lock (&baton))
|
||||
UNEXPECTED (4);
|
||||
/* Step 5: Create the second reader thread. */
|
||||
if (pthread_create (&reader2, NULL, reader2_func, NULL))
|
||||
UNEXPECTED (5);
|
||||
/* Step 6: Release the baton. */
|
||||
if (pthread_mutex_unlock (&baton))
|
||||
UNEXPECTED (6);
|
||||
/* Step 7: The writer thread requests the lock. */
|
||||
if (pthread_rwlock_wrlock (&lock))
|
||||
UNEXPECTED (7);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
reader1 = pthread_self ();
|
||||
|
||||
/* Step 1: The main thread initializes the lock and the baton. */
|
||||
if (pthread_rwlock_init (&lock, NULL))
|
||||
UNEXPECTED (1);
|
||||
if (pthread_mutex_init (&baton, NULL))
|
||||
UNEXPECTED (1);
|
||||
/* Step 2: The main thread acquires the lock as a reader. */
|
||||
if (pthread_rwlock_rdlock (&lock))
|
||||
UNEXPECTED (2);
|
||||
/* Step 3: Create the writer thread. */
|
||||
if (pthread_create (&writer, NULL, writer_func, NULL))
|
||||
UNEXPECTED (3);
|
||||
/* Job done. Go to sleep. */
|
||||
for (;;)
|
||||
{
|
||||
sleep (1);
|
||||
}
|
||||
}
|
||||
]])],
|
||||
[gl_cv_pthread_rwlock_rdlock_prefer_writer=yes],
|
||||
[gl_cv_pthread_rwlock_rdlock_prefer_writer=no],
|
||||
[gl_cv_pthread_rwlock_rdlock_prefer_writer="guessing yes"])
|
||||
LIBS="$save_LIBS"
|
||||
])
|
||||
case "$gl_cv_pthread_rwlock_rdlock_prefer_writer" in
|
||||
*yes)
|
||||
AC_DEFINE([HAVE_PTHREAD_RWLOCK_RDLOCK_PREFER_WRITER], [1],
|
||||
[Define if the 'pthread_rwlock_rdlock' function prefers a writer to a reader.])
|
||||
;;
|
||||
esac
|
||||
])
|
||||
@@ -428,10 +428,10 @@ dump_word_flags (flags)
|
||||
f &= ~W_COMPASSIGN;
|
||||
fprintf (stderr, "W_COMPASSIGN%s", f ? "|" : "");
|
||||
}
|
||||
if (f & W_NOEXPAND)
|
||||
if (f & W_EXPANDRHS)
|
||||
{
|
||||
f &= ~W_NOEXPAND;
|
||||
fprintf (stderr, "W_NOEXPAND%s", f ? "|" : "");
|
||||
f &= ~W_EXPANDRHS;
|
||||
fprintf (stderr, "W_EXPANDRHS%s", f ? "|" : "");
|
||||
}
|
||||
if (f & W_ITILDE)
|
||||
{
|
||||
@@ -3899,7 +3899,8 @@ expand_string_for_rhs (string, quoted, op, pflags, dollar_at_p, expanded_p)
|
||||
in Posix bug 1129 */
|
||||
old_nosplit = expand_no_split_dollar_star;
|
||||
expand_no_split_dollar_star = (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) || op == '=' || ifs_is_null == 0; /* XXX - was 1 */
|
||||
td.flags = W_NOSPLIT2; /* no splitting, remove "" and '' */
|
||||
td.flags = W_EXPANDRHS; /* expanding RHS of ${paramOPword */
|
||||
td.flags |= W_NOSPLIT2; /* no splitting, remove "" and '' */
|
||||
if (pflags & PF_ASSIGNRHS) /* pass through */
|
||||
td.flags |= W_ASSIGNRHS;
|
||||
if (op == '=')
|
||||
@@ -10296,6 +10297,13 @@ add_twochars:
|
||||
this is when we are going to be performing word splitting,
|
||||
since we have to preserve a null argument if the next character
|
||||
will cause word splitting. */
|
||||
if (temp == 0 && quoted_state == PARTIALLY_QUOTED && quoted == 0 && (word->flags & W_NOSPLIT) == 0 && (word->flags & W_EXPANDRHS))
|
||||
{
|
||||
c = CTLNUL;
|
||||
sindex--;
|
||||
had_quoted_null = 1;
|
||||
goto add_character;
|
||||
}
|
||||
if (temp == 0 && quoted_state == PARTIALLY_QUOTED && (word->flags & (W_NOSPLIT|W_NOSPLIT2)))
|
||||
continue;
|
||||
|
||||
@@ -10347,7 +10355,14 @@ add_twochars:
|
||||
/* We do not want to add quoted nulls to strings that are only
|
||||
partially quoted; such nulls are discarded. See above for the
|
||||
exception, which is when the string is going to be split.
|
||||
Posix interp 888 */
|
||||
Posix interp 888/1129 */
|
||||
if (temp == 0 && quoted_state == PARTIALLY_QUOTED && quoted == 0 && (word->flags & W_NOSPLIT) == 0 && (word->flags & W_EXPANDRHS))
|
||||
{
|
||||
c = CTLNUL;
|
||||
sindex--;
|
||||
goto add_character;
|
||||
}
|
||||
|
||||
if (temp == 0 && (quoted_state == PARTIALLY_QUOTED) && (word->flags & (W_NOSPLIT|W_NOSPLIT2)))
|
||||
continue;
|
||||
|
||||
@@ -10478,8 +10493,6 @@ finished_with_string:
|
||||
tword->flags |= W_NOGLOB; /* XXX */
|
||||
if (word->flags & W_NOBRACE)
|
||||
tword->flags |= W_NOBRACE; /* XXX */
|
||||
if (word->flags & W_NOEXPAND)
|
||||
tword->flags |= W_NOEXPAND; /* XXX */
|
||||
if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
|
||||
tword->flags |= W_QUOTED;
|
||||
list = make_word_list (tword, (WORD_LIST *)NULL);
|
||||
@@ -10577,8 +10590,6 @@ set_word_flags:
|
||||
tword->flags |= W_NOGLOB;
|
||||
if (word->flags & W_NOBRACE)
|
||||
tword->flags |= W_NOBRACE;
|
||||
if (word->flags & W_NOEXPAND)
|
||||
tword->flags |= W_NOEXPAND;
|
||||
list = make_word_list (tword, (WORD_LIST *)NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -226,6 +226,7 @@ null fields in rhs
|
||||
null string with unquoted $@
|
||||
argv[1] = <>
|
||||
null string with quoted $@
|
||||
argv[1] = <>
|
||||
assignment
|
||||
argv[1] = <>
|
||||
variable
|
||||
|
||||
+24
-16
@@ -94,7 +94,29 @@ argv[1] = <>
|
||||
argv[1] = <>
|
||||
argv[1] = <>
|
||||
argv[1] = <>
|
||||
argv[2] = <>
|
||||
argv[1] = <>
|
||||
argv[2] = <>
|
||||
argv[1] = <>
|
||||
=====
|
||||
argv[1] = <>
|
||||
argv[1] = <>
|
||||
argv[1] = <>
|
||||
argv[1] = <>
|
||||
argv[2] = <>
|
||||
argv[1] = <>
|
||||
argv[1] = <>
|
||||
argv[1] = <>
|
||||
argv[2] = <>
|
||||
=====
|
||||
argv[1] = <>
|
||||
argv[1] = <>
|
||||
argv[1] = <>
|
||||
argv[1] = <>
|
||||
argv[1] = <>
|
||||
argv[2] = <>
|
||||
argv[1] = <>
|
||||
argv[2] = <>
|
||||
argv[1] = <>
|
||||
=====
|
||||
argv[1] = <>
|
||||
@@ -102,21 +124,7 @@ argv[1] = <>
|
||||
argv[1] = <>
|
||||
argv[1] = <>
|
||||
argv[1] = <>
|
||||
argv[2] = <>
|
||||
argv[1] = <>
|
||||
argv[1] = <>
|
||||
=====
|
||||
argv[1] = <>
|
||||
argv[1] = <>
|
||||
argv[1] = <>
|
||||
argv[1] = <>
|
||||
argv[1] = <>
|
||||
argv[1] = <>
|
||||
argv[1] = <>
|
||||
=====
|
||||
argv[1] = <>
|
||||
argv[1] = <>
|
||||
argv[1] = <>
|
||||
argv[1] = <>
|
||||
argv[1] = <>
|
||||
argv[1] = <>
|
||||
argv[2] = <>
|
||||
argv[1] = <>
|
||||
|
||||
Reference in New Issue
Block a user