]> git.ipfire.org Git - thirdparty/bash.git/commitdiff
commit bash-20190220 snapshot
authorChet Ramey <chet.ramey@case.edu>
Fri, 22 Feb 2019 14:14:00 +0000 (09:14 -0500)
committerChet Ramey <chet.ramey@case.edu>
Fri, 22 Feb 2019 14:14:00 +0000 (09:14 -0500)
13 files changed:
CWRU/CWRU.chlog
MANIFEST
bashhist.c
builtins/cd.def
command.h
configure
configure.ac
doc/bashref.texi
jobs.c
m4/pthread_rwlock_rdlock.m4 [new file with mode: 0644]
subst.c
tests/dollar.right
tests/quote.right

index 54e267c936e68eb34155b570904b346d7027bc60..4442a20d5d76d3f83069f9e96f1ad46a397375b7 100644 (file)
@@ -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
index cf957d3e186d1886f624f307bc71c0fa76be99d6..5c9a37bbbf70e28370a9021eb806c2dd8bd8e302 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -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
index 7912cce311871da3766979ffe60178a4d03ce06d..f7f168ff2d9b16acef6da7bb308d9e06350257e8 100644 (file)
@@ -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);
 
index fe75b57f11990ae597c35ef31ed9b6e27a09c1dd..2e3fcd820117b2d4a0b645865734b4f7ac5c6bbe 100644 (file)
@@ -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;
index b9e9b6693b0b19edcb859465f89a96e5243cd3b3..886aa17dc5f00370d28478f8c13f3e670e42d284 100644 (file)
--- a/command.h
+++ b/command.h
@@ -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 &' */
index db701ff70cca871838600172bef777472748fb7d..f1b6e0d283dd8ea53f6f873e1abc8b20c913507c 100755 (executable)
--- a/configure
+++ b/configure
@@ -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
index ab8bc23f5fb3a80a11f6b754d1452c6c6dc07b25..9eecf8786a26176ba32b3b73ee69f83a6a200eff 100644 (file)
@@ -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])
index a7198fa58296d6f51bd5d81f3d9d023fea62c1a8..89aa6cb614d5ec27f690cac23205edc5e9f0ed74 100644 (file)
@@ -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
diff --git a/jobs.c b/jobs.c
index a23585b19acad2ec8a5daae237166478a5fd7a24..a3905afbac1c2a3ebc0f07d095d2d8dedde5ede1 100644 (file)
--- a/jobs.c
+++ b/jobs.c
@@ -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
diff --git a/m4/pthread_rwlock_rdlock.m4 b/m4/pthread_rwlock_rdlock.m4
new file mode 100644 (file)
index 0000000..3c1d645
--- /dev/null
@@ -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
+])
diff --git a/subst.c b/subst.c
index f9d34ca7ab397ae8327e1463511616cb2ff071cd..ca6634a9e9335e82b3bbafefa8b9a388b7e36948 100644 (file)
--- a/subst.c
+++ b/subst.c
@@ -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);
        }
     }
index d72361f9d185865b3a74c54e265fb5f1415497e7..746ce16b5a2683fdf9d2a8bdc49957ba1ede93ef 100644 (file)
@@ -226,6 +226,7 @@ null fields in rhs
 null string with unquoted $@
 argv[1] = <>
 null string with quoted $@
+argv[1] = <>
 assignment
 argv[1] = <>
 variable
index e4eb9bb95c288481eac43e9526c62624b79022c7..174384aa1b47115075b7bf01ac0941ddf10f7ab5 100644 (file)
@@ -94,23 +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] = <>
@@ -118,5 +124,7 @@ argv[1] = <>
 argv[1] = <>
 argv[1] = <>
 argv[1] = <>
+argv[2] = <>
 argv[1] = <>
+argv[2] = <>
 argv[1] = <>