]> git.ipfire.org Git - thirdparty/bash.git/commitdiff
commit bash-20041005 snapshot
authorChet Ramey <chet.ramey@case.edu>
Sat, 3 Dec 2011 18:37:16 +0000 (13:37 -0500)
committerChet Ramey <chet.ramey@case.edu>
Sat, 3 Dec 2011 18:37:16 +0000 (13:37 -0500)
28 files changed:
CWRU/CWRU.chlog
MANIFEST
braces.c.diff2 [new file with mode: 0644]
builtins/common.c
builtins/declare.def
builtins/reserved.def.new [new file with mode: 0644]
command.h
doc/bash.1
doc/bashref.texi
doc/version.texi
execute_cmd.c
general.h
jobs.c
lib/readline/complete.c
parse.y
subst.c
subst.h
tests/RUN-ONE-TEST
tests/extglob3.right [new file with mode: 0644]
tests/extglob3.tests [new file with mode: 0644]
tests/run-extglob3 [new file with mode: 0644]
tests/run-tilde
tests/run-tilde2 [new file with mode: 0644]
tests/tilde.tests [new file with mode: 0644]
tests/tilde2.right [new file with mode: 0644]
tests/tilde2.tests [new file with mode: 0644]
variables.c
variables.h

index 63804b23db91919d6294dd5631b876bf11eae365..5f7aeddfdb40d46a92a074433bfdb395090e1ba1 100644 (file)
@@ -10155,3 +10155,129 @@ execute_cmd.c
 execute_cmd.c
        - make sure to call UNBLOCK_CHILD before returning on a pipe creation
          failure in execute_pipeline
+
+                                  9/27
+                                  ----
+variables.c
+       - change get_bash_command to deal with the_printed_command_except_trap
+         being NULL
+
+execute_cmd.c
+       - fix execute_simple_command to deal with the_printed_command being
+         NULL when assigning to the_printed_command_except_trap -- fixes
+         seg fault in savestring()
+
+parse.y
+       - change the parser so that the closing `)' in a compound variable
+         assignment delimits a token -- ksh93 does it this way
+
+doc/{bash.1,bashref.texi}
+       - change description of tilde expansion to note that expansion is
+         attempted only after the first =~ in an assignment statement
+
+builtins/declare.def
+       - when assigning to an array variable with declare -a x=(...), make
+         sure the last character in the rhs  of the variable assignment is
+         `)', not just that it appears somewhere
+
+                                  9/28
+                                  ----
+command.h
+       - add a `W_NOEXPAND' flag to inhibit all expansion except quote removal
+       - add a `W_COMPASSIGN' flag to denote a word is a compound assignment
+         statement
+
+parse.y
+       - set W_COMPASSIGN on words that appear to be compound assignments
+
+subst.c
+       - pass W_NOXPAND and W_COMPASSIGN through end of expand_word_internal
+
+subst.[ch]
+       - new function, expand_assignment_string_to_string, calls
+         expand_string_assignment and then string_list on the result
+
+variables.c
+       - assign_in_env now calls expand_assignment_string_to_string
+
+                                  9/30
+                                  ----
+builtins/common.c
+       - change get_job_spec so the null job `%' once again means the current
+         job
+
+                                  10/1
+                                  ----
+subst.c
+       - do_assignment_internal now takes a WORD_DESC * as its first
+         argument, and uses its `word' member as the assignment string
+       - change expand_word_list_internal to call do_word_assignment instead
+         of do_assignment, passing it `word' instead of, e.g., `word->word'
+       - change extract_array_assignment_list to just return the passed
+         string minus a trailing `)' if the last character is a right
+         paren
+       - change do_assignment_internal to call extract_array_assignment_list
+
+subst.[ch]
+       - change do_assignment and do_assignment_no_expand to take a `char *'
+         instead of `const char *' first argument; change extern prototypes
+       - new function, do_word_assignment, takes a WORD_DESC * and calls
+         do_assignment_internal on it; add extern declaration with prototype
+
+general.h
+       - new typedef, sh_wassign_func_t, like sh_assign_func_t but takes a
+         WORD_DESC * as its first argument
+
+variables.[ch]
+       - assign_in_env now takes a WORD_DESC * as its first argument
+
+                                  10/2
+                                  ----
+command.h
+       - new word flag, W_ASSNBLTIN, denotes that the word is a builtin
+         command (in a command position) that takes assignment statements
+         as arguments, like `declare'
+       - new word flags, W_ASSIGNARG, denotes that word is an assignment
+         statement given as argument to assignment builtin
+
+execute_cmd.c
+       - set W_ASSNBLTIN flag in fix_assignment_words if necessary (if there
+         are any arguments that are assignment statements)
+       - set W_ASSIGNARG flag in fix_assignment_words if necessary
+
+subst.c
+       - new function, do_compound_assignment, encapsulates the necessary
+         code to perform a compound array assignment (including creation of
+         local variables); called from do_assignment_internal
+       - to fix the double-expansion problem with compound array assignments
+         that are arguments to builtins like `declare', changed
+         shell_expand_word_list to treat those arguments like assignment
+         statements (with proper creation of local variables inside shell
+         functions) and pass the attribute-setting portion of the statement
+         onto the builtin.  This is what ksh93 appears to do, from inspection
+         of the `ksh93 -x' output
+
+execute_cmd.c
+       - fix execute_simple_command:  in case of pipeline or async command,
+         when forking early, set `subshell_environment' so that it can contain
+         both SUBSHELL_PIPE and SUBSHELL_ASYNC -- the two should not be
+         mutually exclusive.  Fixes bug reported by pierre.humblet@ieee.org
+       - remove references to last_pid, old_command_subst_pid; use NO_PID as
+         a sentinel value to decide whether or not a child process has been
+         created and needs to be waited for.  Submitted by
+         pierre.humblet@ieee.org to fix recycling-pid problem on cygwin
+
+doc/{bash.1,bashref.texi}
+       - fixed documentation of `@(pattern)' extended globbing operator --
+         it succeeds if the string matches one of the patterns, not exactly
+         one.  This is what ksh93 does, too
+
+lib/readline/complete.c
+       - fixed rl_menu_complete so that a negative argument cycles backwards
+         through the list
+
+                                  10/3
+                                  ----
+subst.c
+       - use W_COMPASSIGN flag in do_assignment_internal instead of deciding
+         lexically which assignments are compound array assignments
index 398d522df6bfff5ad666e876e96cdf8a2426479c..2985f5402517bc3e6754aa7619f71b9bee23a27d 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -731,6 +731,8 @@ tests/extglob.tests f
 tests/extglob.right    f
 tests/extglob2.tests   f
 tests/extglob2.right   f
+tests/extglob3.tests   f
+tests/extglob3.right   f
 tests/func.tests       f
 tests/func.right       f
 tests/func1.sub                f
@@ -840,6 +842,7 @@ tests/run-execscript        f
 tests/run-exp-tests    f
 tests/run-extglob      f
 tests/run-extglob2     f
+tests/run-extglob3     f
 tests/run-func         f
 tests/run-getopts      f
 tests/run-glob-test    f
@@ -873,6 +876,7 @@ tests/run-shopt             f
 tests/run-strip                f
 tests/run-test         f
 tests/run-tilde                f
+tests/run-tilde2       f
 tests/run-trap         f
 tests/run-type         f
 tests/run-varenv       f
@@ -886,8 +890,10 @@ tests/strip.tests  f
 tests/strip.right      f
 tests/test.tests       f
 tests/test.right       f
-tests/tilde-tests      f
+tests/tilde.tests      f
 tests/tilde.right      f
+tests/tilde2.tests     f
+tests/tilde2.right     f
 tests/trap.tests       f
 tests/trap.right       f
 tests/trap1.sub                f       755
diff --git a/braces.c.diff2 b/braces.c.diff2
new file mode 100644 (file)
index 0000000..7558551
--- /dev/null
@@ -0,0 +1,16 @@
+*** ../bash-3.0-patched/braces.c       Wed Sep  8 11:07:53 2004
+--- braces.c   Fri Sep 17 18:42:36 2004
+***************
+*** 403,407 ****
+         pass_next = 1;
+         i++;
+!        level++;
+         continue;
+       }
+--- 403,408 ----
+         pass_next = 1;
+         i++;
+!        if (quoted == 0)
+!          level++;
+         continue;
+       }
index 8c2dde4a2f9a6a1c11c4417f9aff02f41714b97d..b7ea0006e27fa0464ca0231031818d45a00490af 100644 (file)
@@ -588,7 +588,6 @@ get_job_spec (list)
   switch (*word)
     {
     case 0:
-       return NO_JOB;
     case '%':
     case '+':
       return (current_job);
index fe112dd6f88474d1b95e0218c267f994a50efc44..3afed551842e8912100c3bf06a7baa66f5ebf620 100644 (file)
@@ -377,7 +377,13 @@ declare_internal (list, local_var)
 #if defined (ARRAY_VARS)
          if ((making_array_special || (flags_on & att_array) || array_p (var)) && offset)
            {
+             int vlen;
+             vlen = STRLEN (value);
+#if 0
              if (value[0] == '(' && strchr (value, ')'))
+#else
+             if (value[0] == '(' && value[vlen-1] == ')')
+#endif
                compound_array_assign = 1;
              else
                simple_array_assign = 1;
diff --git a/builtins/reserved.def.new b/builtins/reserved.def.new
new file mode 100644 (file)
index 0000000..76e5965
--- /dev/null
@@ -0,0 +1,203 @@
+This file is reserved.def, in which the shell reserved words are defined.
+It has no direct C file production, but defines builtins for the Bash
+builtin help command.
+
+Copyright (C) 1987-2002 Free Software Foundation, Inc.
+
+This file is part of GNU Bash, the Bourne Again SHell.
+
+Bash is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with Bash; see the file COPYING.  If not, write to the Free Software
+Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA.
+
+$BUILTIN for
+$SHORT_DOC for NAME [in WORDS ... ;] do COMMANDS; done
+The `for' loop executes a sequence of commands for each member in a
+list of items.  If `in WORDS ...;' is not present, then `in "$@"' is
+assumed.  For each element in WORDS, NAME is set to that element, and
+the COMMANDS are executed.
+$END
+
+$BUILTIN for ((
+$DOCNAME arith_for
+$SHORT_DOC for (( exp1; exp2; exp3 )); do COMMANDS; done
+Equivalent to
+       (( EXP1 ))
+       while (( EXP2 )); do
+               COMMANDS
+               (( EXP3 ))
+       done
+EXP1, EXP2, and EXP3 are arithmetic expressions.  If any expression is
+omitted, it behaves as if it evaluates to 1.
+$END
+
+$BUILTIN select
+$SHORT_DOC select NAME [in WORDS ... ;] do COMMANDS; done
+The WORDS are expanded, generating a list of words.  The
+set of expanded words is printed on the standard error, each
+preceded by a number.  If `in WORDS' is not present, `in "$@"'
+is assumed.  The PS3 prompt is then displayed and a line read
+from the standard input.  If the line consists of the number
+corresponding to one of the displayed words, then NAME is set
+to that word.  If the line is empty, WORDS and the prompt are
+redisplayed.  If EOF is read, the command completes.  Any other
+value read causes NAME to be set to null.  The line read is saved
+in the variable REPLY.  COMMANDS are executed after each selection
+until a break command is executed.
+$END
+
+$BUILTIN time
+$SHORT_DOC time [-p] PIPELINE
+Execute PIPELINE and print a summary of the real time, user CPU time,
+and system CPU time spent executing PIPELINE when it terminates.
+The return status is the return status of PIPELINE.  The `-p' option
+prints the timing summary in a slightly different format.  This uses
+the value of the TIMEFORMAT variable as the output format.
+$END
+
+$BUILTIN case
+$SHORT_DOC case WORD in [PATTERN [| PATTERN]...) COMMANDS ;;]... esac
+Selectively execute COMMANDS based upon WORD matching PATTERN.  The
+`|' is used to separate multiple patterns.
+$END
+
+$BUILTIN if
+$SHORT_DOC if COMMANDS; then COMMANDS; [ elif COMMANDS; then COMMANDS; ]... [ else COMMANDS; ] fi
+The if COMMANDS are executed.  If the exit status is zero, then the then
+COMMANDS are executed.  Otherwise, each of the elif COMMANDS are executed
+in turn, and if the exit status is zero, the corresponding then COMMANDS
+are executed and the if command completes.  Otherwise, the else COMMANDS
+are executed, if present.  The exit status is the exit status of the last
+command executed, or zero if no condition tested true.
+$END
+
+$BUILTIN while
+$SHORT_DOC while COMMANDS; do COMMANDS; done
+Expand and execute COMMANDS as long as the final command in the
+`while' COMMANDS has an exit status of zero.
+$END
+
+$BUILTIN until
+$SHORT_DOC until COMMANDS; do COMMANDS; done
+Expand and execute COMMANDS as long as the final command in the
+`until' COMMANDS has an exit status which is not zero.
+$END
+
+$BUILTIN function
+$SHORT_DOC function NAME { COMMANDS ; } or NAME () { COMMANDS ; }
+Create a simple command invoked by NAME which runs COMMANDS.
+Arguments on the command line along with NAME are passed to the
+function as $0 .. $n.
+$END
+
+$BUILTIN { ... }
+$DOCNAME grouping_braces
+$SHORT_DOC { COMMANDS ; }
+Run a set of commands in a group.  This is one way to redirect an
+entire set of commands.
+$END
+
+$BUILTIN %
+$DOCNAME fg_percent
+$SHORT_DOC job_spec [&]
+Equivalent to the JOB_SPEC argument to the `fg' command.  Resume a
+stopped or background job.  JOB_SPEC can specify either a job name
+or a job number.  Following JOB_SPEC with a `&' places the job in
+the background, as if the job specification had been supplied as an
+argument to `bg'.
+$END
+
+$BUILTIN (( ... ))
+$DOCNAME arith
+$SHORT_DOC (( expression ))
+The EXPRESSION is evaluated according to the rules for arithmetic
+evaluation.  Equivalent to "let EXPRESSION".
+$END
+
+$BUILTIN [[ ... ]]
+$DOCNAME conditional
+$SHORT_DOC [[ expression ]]
+Returns a status of 0 or 1 depending on the evaluation of the conditional
+expression EXPRESSION.  Expressions are composed of the same primaries used
+by the `test' builtin, and may be combined using the following operators
+
+       ( EXPRESSION )  Returns the value of EXPRESSION
+       ! EXPRESSION    True if EXPRESSION is false; else false
+       EXPR1 && EXPR2  True if both EXPR1 and EXPR2 are true; else false
+       EXPR1 || EXPR2  True if either EXPR1 or EXPR2 is true; else false
+
+When the `==' and `!=' operators are used, the string to the right of the
+operator is used as a pattern and pattern matching is performed.  The
+&& and || operators do not evaluate EXPR2 if EXPR1 is sufficient to
+determine the expression's value.
+$END
+
+$BUILTIN variables
+$DOCNAME variable_help
+$SHORT_DOC variables - Some variable names and meanings
+BASH_VERSION    Version information for this Bash.
+CDPATH          A colon separated list of directories to search
+               when the argument to `cd' is not found in the current
+               directory.
+GLOBIGNORE     A colon-separated list of patterns describing filenames to
+               be ignored by pathname expansion.
+#if defined (HISTORY)
+HISTFILE        The name of the file where your command history is stored.
+HISTFILESIZE    The maximum number of lines this file can contain.
+HISTSIZE        The maximum number of history lines that a running
+               shell can access.
+#endif /* HISTORY */
+HOME            The complete pathname to your login directory.
+HOSTNAME       The name of the current host.
+HOSTTYPE        The type of CPU this version of Bash is running under.
+IGNOREEOF       Controls the action of the shell on receipt of an EOF
+               character as the sole input.  If set, then the value
+               of it is the number of EOF characters that can be seen
+               in a row on an empty line before the shell will exit
+               (default 10).  When unset, EOF signifies the end of input.
+MACHTYPE       A string describing the current system Bash is running on.
+MAILCHECK      How often, in seconds, Bash checks for new mail.
+MAILPATH       A colon-separated list of filenames which Bash checks
+               for new mail.
+OSTYPE         The version of Unix this version of Bash is running on.
+PATH            A colon-separated list of directories to search when
+               looking for commands.
+PROMPT_COMMAND  A command to be executed before the printing of each
+               primary prompt.
+PS1             The primary prompt string.
+PS2             The secondary prompt string.
+PWD            The full pathname of the current directory.
+SHELLOPTS      A colon-separated list of enabled shell options.
+TERM            The name of the current terminal type.
+TIMEFORMAT     The output format for timing statistics displayed by the
+               `time' reserved word.
+auto_resume     Non-null means a command word appearing on a line by
+               itself is first looked for in the list of currently
+               stopped jobs.  If found there, that job is foregrounded.
+               A value of `exact' means that the command word must
+               exactly match a command in the list of stopped jobs.  A
+               value of `substring' means that the command word must
+               match a substring of the job.  Any other value means that
+               the command must be a prefix of a stopped job.
+#if defined (HISTORY)
+#  if defined (BANG_HISTORY)
+histchars       Characters controlling history expansion and quick
+               substitution.  The first character is the history
+               substitution character, usually `!'.  The second is
+               the `quick substitution' character, usually `^'.  The
+               third is the `history comment' character, usually `#'.
+#  endif /* BANG_HISTORY */
+HISTIGNORE     A colon-separated list of patterns used to decide which
+               commands should be saved on the history list.
+#endif /* HISTORY */
+$END
index 8d05376fbce573973105de9bc32e598194ee6777..7cfeaf76319d36d0d86714188a33582f7a7c0f74 100644 (file)
--- a/command.h
+++ b/command.h
@@ -67,20 +67,24 @@ enum command_type { cm_for, cm_case, cm_while, cm_if, cm_simple, cm_select,
                    cm_arith, cm_cond, cm_arith_for, cm_subshell };
 
 /* Possible values for the `flags' field of a WORD_DESC. */
-#define W_HASDOLLAR    0x0001  /* Dollar sign present. */
-#define W_QUOTED       0x0002  /* Some form of quote character is present. */
-#define W_ASSIGNMENT   0x0004  /* This word is a variable assignment. */
-#define W_GLOBEXP      0x0008  /* This word is the result of a glob expansion. */
-#define W_NOSPLIT      0x0010  /* Do not perform word splitting on this word. */
-#define W_NOGLOB       0x0020  /* Do not perform globbing on this word. */
-#define W_NOSPLIT2     0x0040  /* Don't split word except for $@ expansion. */
-#define W_TILDEEXP     0x0080  /* Tilde expand this assignment word */
-#define W_DOLLARAT     0x0100  /* $@ and its special handling */
-#define W_DOLLARSTAR   0x0200  /* $* and its special handling */
-#define W_NOCOMSUB     0x0400  /* Don't perform command substitution on this word */
-#define W_ASSIGNRHS    0x0800  /* Word is rhs of an assignment statement */
-#define W_NOTILDE      0x1000  /* Don't perform tilde expansion on this word */
-#define W_ITILDE       0x2000  /* Internal flag for word expansion */
+#define W_HASDOLLAR    0x00001 /* Dollar sign present. */
+#define W_QUOTED       0x00002 /* Some form of quote character is present. */
+#define W_ASSIGNMENT   0x00004 /* This word is a variable assignment. */
+#define W_GLOBEXP      0x00008 /* This word is the result of a glob expansion. */
+#define W_NOSPLIT      0x00010 /* Do not perform word splitting on this word. */
+#define W_NOGLOB       0x00020 /* Do not perform globbing on this word. */
+#define W_NOSPLIT2     0x00040 /* Don't split word except for $@ expansion. */
+#define W_TILDEEXP     0x00080 /* Tilde expand this assignment word */
+#define W_DOLLARAT     0x00100 /* $@ and its special handling */
+#define W_DOLLARSTAR   0x00200 /* $* and its special handling */
+#define W_NOCOMSUB     0x00400 /* Don't perform command substitution on this word */
+#define W_ASSIGNRHS    0x00800 /* Word is rhs of an assignment statement */
+#define W_NOTILDE      0x01000 /* Don't perform tilde expansion on this word */
+#define W_ITILDE       0x02000 /* Internal flag for word expansion */
+#define W_NOEXPAND     0x04000 /* Don't expand at all -- do quote removal */
+#define W_COMPASSIGN   0x08000 /* Compound assignment */
+#define W_ASSNBLTIN    0x10000 /* word is a builtin command that takes assignments */
+#define W_ASSIGNARG    0x20000 /* word is assignment argument to command */
 
 /* Possible values for subshell_environment */
 #define SUBSHELL_ASYNC 0x01    /* subshell caused by `command &' */
index cbd986df68ff571263df3bf88580c5537b1cd64b..e0d7f797bd7d3f09031ff0adf7b53cd962c96b74 100644 (file)
@@ -6,12 +6,12 @@
 .\"    Case Western Reserve University
 .\"    chet@po.CWRU.Edu
 .\"
-.\"    Last Change: Fri Sep 17 22:44:17 EDT 2004
+.\"    Last Change: Sat Oct  2 18:05:57 EDT 2004
 .\"
 .\" bash_builtins, strip all but Built-Ins section
 .if \n(zZ=1 .ig zZ
 .if \n(zY=1 .ig zY
-.TH BASH 1 "2004 Sep 17" "GNU Bash-3.0"
+.TH BASH 1 "2004 Oct 2" "GNU Bash-3.1-devel"
 .\"
 .\" There's some problem with having a `@'
 .\" in a tagged paragraph with the BSD man macros.
@@ -2236,7 +2236,7 @@ is unchanged.
 Each variable assignment is checked for unquoted tilde-prefixes immediately
 following a
 .B :
-or
+or the first
 .BR = .
 In these cases, tilde expansion is also performed.
 Consequently, one may use file names with tildes in assignments to
@@ -2853,7 +2853,7 @@ Matches zero or more occurrences of the given patterns
 Matches one or more occurrences of the given patterns
 .TP
 \fB@(\fP\^\fIpattern-list\^\fP\fB)\fP
-Matches exactly one of the given patterns
+Matches one of the given patterns
 .TP
 \fB!(\fP\^\fIpattern-list\^\fP\fB)\fP
 Matches anything except one of the given patterns
@@ -4063,6 +4063,8 @@ command), the current job is always flagged with a
 .BR + ,
 and the previous job with a
 .BR \- .
+A single % (with no accompanying job specification) also refers to the
+current job.
 .PP
 Simply naming a job can be used to bring it into the
 foreground:
index eb460797256f0c03de87d3b2c40a3bf87a875b09..9df7ead7b63afe2ba5447868e63c1eb70e942d84 100644 (file)
@@ -1456,7 +1456,7 @@ If the login name is invalid, or the tilde expansion fails, the word is
 left unchanged.
 
 Each variable assignment is checked for unquoted tilde-prefixes immediately
-following a @samp{:} or @samp{=}.
+following a @samp{:} or the first @samp{=}.
 In these cases, tilde expansion is also performed.
 Consequently, one may use file names with tildes in assignments to
 @env{PATH}, @env{MAILPATH}, and @env{CDPATH},
@@ -1931,7 +1931,7 @@ Matches zero or more occurrences of the given patterns.
 Matches one or more occurrences of the given patterns.
 
 @item @@(@var{pattern-list})
-Matches exactly one of the given patterns.
+Matches one of the given patterns.
 
 @item !(@var{pattern-list})
 Matches anything except one of the given patterns.
@@ -6118,11 +6118,12 @@ There are a number of ways to refer to a job in the shell.  The
 character @samp{%} introduces a job name.
 
 Job number @code{n} may be referred to as @samp{%n}.
-The symbols @samp{%%} and
-@samp{%+} refer to the shell's notion of the current job, which
-is the last job stopped while it was in the foreground or started
-in the background.  The
-previous job may be referenced using @samp{%-}.  In output
+The symbols @samp{%%} and  @samp{%+} refer to the shell's notion of the
+current job, which is the last job stopped while it was in the foreground
+or started in the background.
+A single @samp{%} (with no accompanying job specification) also refers
+to the current job.
+The previous job may be referenced using @samp{%-}.  In output
 pertaining to jobs (e.g., the output of the @code{jobs} command),
 the current job is always flagged with a @samp{+}, and the
 previous job with a @samp{-}. 
index 2b47057ccd6bcd4c4919a534d0633a0090d5bf55..af20a424a875199a183ed1ebfda928fa2f5506a6 100644 (file)
@@ -2,9 +2,9 @@
 Copyright (C) 1988-2004 Free Software Foundation, Inc.
 @end ignore
 
-@set EDITION 3.0
-@set VERSION 3.0
-@set UPDATED 17 September 2004
-@set UPDATED-MONTH September 2004
+@set EDITION 3.1-devel
+@set VERSION 3.1-devel
+@set UPDATED 2 October 2004
+@set UPDATED-MONTH October 2004
 
-@set LASTCHANGE Fri Sep 17 22:43:56 EDT 2004
+@set LASTCHANGE Sat Oct  2 18:05:41 EDT 2004
index 98c4a426d502f2a2bf3fa6b1b731caf4baecea0b..968f23454cc9f69bb10a8dd5185d86864442e162 100644 (file)
@@ -160,7 +160,7 @@ static int execute_while_command __P((WHILE_COM *));
 static int execute_until_command __P((WHILE_COM *));
 static int execute_while_or_until __P((WHILE_COM *, int));
 static int execute_if_command __P((IF_COM *));
-static int execute_null_command __P((REDIRECT *, int, int, int, pid_t));
+static int execute_null_command __P((REDIRECT *, int, int, int));
 static void fix_assignment_words __P((WORD_LIST *));
 static int execute_simple_command __P((SIMPLE_COM *, int, int, int, struct fd_bitmap *));
 static int execute_builtin __P((sh_builtin_func_t *, WORD_LIST *, int, int));
@@ -491,7 +491,6 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
 {
   int exec_result, invert, ignore_return, was_error_trap;
   REDIRECT *my_undo_list, *exec_undo_list;
-  volatile pid_t last_pid;
   volatile int save_line_number;
 
   if (command == 0 || breaking || continuing || read_but_dont_execute)
@@ -648,7 +647,7 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
        /* We can't rely on variables retaining their values across a
           call to execute_simple_command if a longjmp occurs as the
           result of a `return' builtin.  This is true for sure with gcc. */
-       last_pid = last_made_pid;
+       last_made_pid = NO_PID;
        was_error_trap = signal_is_trapped (ERROR_TRAP) && signal_is_ignored (ERROR_TRAP) == 0;
 
        if (ignore_return && command->value.Simple)
@@ -678,7 +677,7 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
        /* XXX - this is something to watch out for if there are problems
           when the shell is compiled without job control. */
        if (already_making_children && pipe_out == NO_PIPE &&
-           last_pid != last_made_pid)
+           last_made_pid != NO_PID)
          {
            stop_pipeline (asynchronous, (COMMAND *)NULL);
 
@@ -698,14 +697,6 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
               subshells forked to execute builtin commands (e.g., in
               pipelines) to be waited for twice. */
              exec_result = wait_for (last_made_pid);
-#if defined (RECYCLES_PIDS)
-             /* LynxOS, for one, recycles pids very quickly -- so quickly
-                that a new process may have the same pid as the last one
-                created.  This has been reported to fix the problem on that
-                OS, and a similar problem on Cygwin. */
-             if (exec_result == 0)
-               last_made_pid = NO_PID;
-#endif
          }
       }
 
@@ -2583,10 +2574,9 @@ bind_lastarg (arg)
    to be run asynchronously.  This handles all the side effects that are
    supposed to take place. */
 static int
-execute_null_command (redirects, pipe_in, pipe_out, async, old_last_command_subst_pid)
+execute_null_command (redirects, pipe_in, pipe_out, async)
      REDIRECT *redirects;
      int pipe_in, pipe_out, async;
-     pid_t old_last_command_subst_pid;
 {
   int r;
 
@@ -2632,7 +2622,7 @@ execute_null_command (redirects, pipe_in, pipe_out, async, old_last_command_subs
 
       if (r != 0)
        return (EXECUTION_FAILURE);
-      else if (old_last_command_subst_pid != last_command_subst_pid)
+      else if (last_command_subst_pid != NO_PID)
        return (last_command_exit_value);
       else
        return (EXECUTION_SUCCESS);
@@ -2661,8 +2651,10 @@ fix_assignment_words (words)
            b = builtin_address_internal (words->word->word, 0);
            if (b == 0 || (b->flags & ASSIGNMENT_BUILTIN) == 0)
              return;
+           else if (b && (b->flags & ASSIGNMENT_BUILTIN))
+             words->word->flags |= W_ASSNBLTIN;
          }
-       w->word->flags |= (W_NOSPLIT|W_NOGLOB|W_TILDEEXP);
+       w->word->flags |= (W_NOSPLIT|W_NOGLOB|W_TILDEEXP|W_ASSIGNARG);
       }
 }
 
@@ -2678,7 +2670,7 @@ execute_simple_command (simple_command, pipe_in, pipe_out, async, fds_to_close)
   WORD_LIST *words, *lastword;
   char *command_line, *lastarg, *temp;
   int first_word_quoted, result, builtin_is_special, already_forked, dofork;
-  pid_t old_last_command_subst_pid, old_last_async_pid;
+  pid_t old_last_async_pid;
   sh_builtin_func_t *builtin;
   SHELL_VAR *func;
 
@@ -2697,7 +2689,7 @@ execute_simple_command (simple_command, pipe_in, pipe_out, async, fds_to_close)
   if (this_command_name == 0 || (STREQ (this_command_name, "trap") == 0))
     {
       FREE (the_printed_command_except_trap);
-      the_printed_command_except_trap = savestring (the_printed_command);
+      the_printed_command_except_trap = the_printed_command ? savestring (the_printed_command) : (char *)0;
     }
 
   /* Run the debug trap before each simple command, but do it after we
@@ -2713,7 +2705,7 @@ execute_simple_command (simple_command, pipe_in, pipe_out, async, fds_to_close)
   first_word_quoted =
     simple_command->words ? (simple_command->words->word->flags & W_QUOTED): 0;
 
-  old_last_command_subst_pid = last_command_subst_pid;
+  last_command_subst_pid = NO_PID;
   old_last_async_pid = last_asynchronous_pid;
 
   already_forked = dofork = 0;
@@ -2752,9 +2744,17 @@ execute_simple_command (simple_command, pipe_in, pipe_out, async, fds_to_close)
          already_forked = 1;
          simple_command->flags |= CMD_NO_FORK;
 
+#if 0
          subshell_environment = (pipe_in != NO_PIPE || pipe_out != NO_PIPE)
                                        ? (SUBSHELL_PIPE|SUBSHELL_FORK)
                                        : (SUBSHELL_ASYNC|SUBSHELL_FORK);
+#else
+         subshell_environment = SUBSHELL_FORK;
+         if (pipe_in != NO_PIPE || pipe_out != NO_PIPE)
+           subshell_environment |= SUBSHELL_PIPE;
+         if (async)
+           subshell_environment |= SUBSHELL_ASYNC;
+#endif
 
          /* We need to do this before piping to handle some really
             pathological cases where one of the pipe file descriptors
@@ -2799,8 +2799,7 @@ execute_simple_command (simple_command, pipe_in, pipe_out, async, fds_to_close)
       this_command_name = 0;
       result = execute_null_command (simple_command->redirects,
                                     pipe_in, pipe_out,
-                                    already_forked ? 0 : async,
-                                    old_last_command_subst_pid);
+                                    already_forked ? 0 : async);
       if (already_forked)
        exit (result);
       else
index ce76e1633e5dfe43d0cbe382f2ce5e82d6c3acb6..f4d001b71465f1abc2bc84113c13d3406bb4c765 100644 (file)
--- a/general.h
+++ b/general.h
@@ -216,6 +216,7 @@ typedef void sh_resetsig_func_t __P((int)); /* sh_vintfunc_t */
 typedef int sh_ignore_func_t __P((const char *));      /* sh_icpfunc_t */
 
 typedef int sh_assign_func_t __P((const char *));      /* sh_icpfunc_t */
+typedef int sh_wassign_func_t __P((WORD_DESC *));
 
 typedef int sh_builtin_func_t __P((WORD_LIST *)); /* sh_wlist_func_t */
 
diff --git a/jobs.c b/jobs.c
index b89cf242762be60d0396968f91ec82550679bcb7..3747ec1613cf9fc66d23186fb52cb227b5f86afa 100644 (file)
--- a/jobs.c
+++ b/jobs.c
@@ -129,7 +129,8 @@ extern int errno;
 #endif /* !MUST_REINSTALL_SIGHANDLERS */
 
 /* Some systems let waitpid(2) tell callers about stopped children. */
-#if !defined (WCONTINUED)
+#if !defined (WCONTINUED) || defined (WCONTINUED_BROKEN)
+#  undef WCONTINUED
 #  define WCONTINUED 0
 #endif
 #if !defined (WIFCONTINUED)
index 14d818793cb0ce93bb34d8578d775332b47db116..a065e9b7f7798627f2b3dd671542b1aaf7a35d1c 100644 (file)
@@ -2178,9 +2178,11 @@ rl_menu_complete (count, ignore)
       return (0);
     }
 
-  match_list_index = (match_list_index + count) % match_list_size;
+  match_list_index += count;
   if (match_list_index < 0)
     match_list_index += match_list_size;
+  else
+    match_list_index %= match_list_size;
 
   if (match_list_index == 0 && match_list_size > 1)
     {
diff --git a/parse.y b/parse.y
index 4b448ad0a6dac7ffe3b4313f37105713e473c259..5acbaef796c003828930b79e61f34fda97720d85 100644 (file)
--- a/parse.y
+++ b/parse.y
@@ -3285,6 +3285,10 @@ read_token_word (character)
   /* DOLLAR_PRESENT becomes non-zero if we see a `$'. */
   int dollar_present;
 
+  /* COMPOUND_ASSIGNMENT becomes non-zero if we are parsing a compound
+     assignment. */
+  int compound_assignment;
+
   /* QUOTED becomes non-zero if we see one of ("), ('), (`), or (\). */
   int quoted;
 
@@ -3304,7 +3308,7 @@ read_token_word (character)
 
   token_index = 0;
   all_digit_token = DIGIT (character);
-  dollar_present = quoted = pass_next_character = 0;
+  dollar_present = quoted = pass_next_character = compound_assignment = 0;
 
   for (;;)
     {
@@ -3543,7 +3547,12 @@ read_token_word (character)
              token[token_index++] = ')';
              FREE (ttok);
              all_digit_token = 0;
+             compound_assignment = 1;
+#if 0
              goto next_character;
+#else
+             goto got_token;           /* ksh93 seems to do this */
+#endif
            }
          else
            shell_ungetc (peek_char);
@@ -3638,6 +3647,8 @@ got_token:
     the_word->flags |= W_HASDOLLAR;
   if (quoted)
     the_word->flags |= W_QUOTED;
+  if (compound_assignment)
+    the_word->flags |= W_COMPASSIGN;
   /* A word is an assignment if it appears at the beginning of a
      simple command, or after another assignment word.  This is
      context-dependent, so it cannot be handled in the grammar. */
diff --git a/subst.c b/subst.c
index 9a1e0f0e4b5727cfe2ae7d321ea01a103ad12803..1372bf80460f51e83d248b83a0cbc44dcaca1d68 100644 (file)
--- a/subst.c
+++ b/subst.c
@@ -204,7 +204,10 @@ static char *remove_quoted_nulls __P((char *));
 static int unquoted_substring __P((char *, char *));
 static int unquoted_member __P((int, char *));
 
-static int do_assignment_internal __P((const char *, int));
+#if defined (ARRAY_VARS)
+static SHELL_VAR *do_compound_assignment __P((char *, char *, int));
+#endif
+static int do_assignment_internal __P((const WORD_DESC *, int));
 
 static char *string_extract_verbatim __P((char *, int *, char *));
 static char *string_extract __P((char *, int *, char *, int));
@@ -983,12 +986,28 @@ extract_process_subst (string, starter, sindex)
 #endif /* PROCESS_SUBSTITUTION */
 
 #if defined (ARRAY_VARS)
+/* This can be fooled by unquoted right parens in the passed string. If
+   each caller verifies that the last character in STRING is a right paren,
+   we don't even need to call extract_delimited_string. */
 char *
 extract_array_assignment_list (string, sindex)
      char *string;
      int *sindex;
 {
+#if 0
   return (extract_delimited_string (string, sindex, "(", (char *)NULL, ")", 0));
+#else
+  int slen;
+  char *ret;
+
+  slen = strlen (string);      /* ( */
+  if (string[slen - 1] == ')')
+   {
+      ret = substring (string, *sindex, slen - 1);
+      *sindex = slen - 1;
+      return ret;
+    }
+#endif
 }
 #endif
 
@@ -2122,17 +2141,40 @@ list_string_with_quotes (string)
 /*                                                     */
 /********************************************************/
 
+#if defined (ARRAY_VARS)
+static SHELL_VAR *
+do_compound_assignment (name, value, mklocal)
+     char *name, *value;
+     int mklocal;
+{
+  SHELL_VAR *v;
+  int off;
+
+  if (mklocal && variable_context)
+    {
+      v = find_variable (name);
+      if (v == 0 || array_p (v) == 0)
+        v = make_local_array_variable (name);
+      v = assign_array_var_from_string (v, value);
+    }
+  else
+    v = assign_array_from_string (name, value);
+
+  return (v);
+}
+#endif
+
 /* Given STRING, an assignment string, get the value of the right side
    of the `=', and bind it to the left side.  If EXPAND is true, then
    perform parameter expansion, command substitution, and arithmetic
    expansion on the right-hand side.  Perform tilde expansion in any
    case.  Do not perform word splitting on the result of expansion. */
 static int
-do_assignment_internal (string, expand)
-     const char *string;
+do_assignment_internal (word, expand)
+     const WORD_DESC *word;
      int expand;
 {
-  int offset;
+  int offset, tlen;
   char *name, *value;
   SHELL_VAR *entry;
 #if defined (ARRAY_VARS)
@@ -2140,7 +2182,12 @@ do_assignment_internal (string, expand)
   int ni;
 #endif
   int assign_list = 0;
+  const char *string;
 
+  if (word == 0 || word->word == 0)
+    return 0;
+
+  string = word->word;
   offset = assignment (string, 0);
   name = savestring (string);
   value = (char *)NULL;
@@ -2151,17 +2198,21 @@ do_assignment_internal (string, expand)
 
       name[offset] = 0;
       temp = name + offset + 1;
+      tlen = STRLEN (temp);
 
 #if defined (ARRAY_VARS)
-      if (expand && temp[0] == LPAREN && xstrchr (temp, RPAREN))
+#  if 0
+      if (expand && temp[0] == LPAREN && temp[tlen-1] == RPAREN)
+#else
+      if (expand && (word->flags & W_COMPASSIGN))
+#endif
        {
          assign_list = ni = 1;
-         value = extract_delimited_string (temp, &ni, "(", (char *)NULL, ")", 0);
+         value = extract_array_assignment_list (temp, &ni);
        }
       else
 #endif
 
-      /* Perform tilde expansion. */
       if (expand && temp[0])
        value = expand_string_if_necessary (temp, 0, expand_string_assignment);
       else
@@ -2192,7 +2243,7 @@ do_assignment_internal (string, expand)
        ASSIGN_RETURN (0);
     }
   else if (assign_list)
-    entry = assign_array_from_string (name, value);
+    entry = do_compound_assignment (name, value, (word->flags & W_ASSIGNARG));
   else
 #endif /* ARRAY_VARS */
   entry = bind_variable (name, value);
@@ -2207,22 +2258,39 @@ do_assignment_internal (string, expand)
 }
 
 /* Perform the assignment statement in STRING, and expand the
-   right side by doing command and parameter expansion. */
+   right side by doing tilde, command and parameter expansion. */
 int
 do_assignment (string)
-     const char *string;
+     char *string;
 {
-  return do_assignment_internal (string, 1);
+  WORD_DESC td;
+
+  td.flags = W_ASSIGNMENT;
+  td.word = string;
+
+  return do_assignment_internal (&td, 1);
+}
+
+int
+do_word_assignment (word)
+     WORD_DESC *word;
+{
+  return do_assignment_internal (word, 1);
 }
 
 /* Given STRING, an assignment string, get the value of the right side
-   of the `=', and bind it to the left side.  Do not do command and
-   parameter substitution on the right hand side. */
+   of the `=', and bind it to the left side.  Do not perform any word
+   expansions on the right hand side. */
 int
 do_assignment_no_expand (string)
-     const char *string;
+     char *string;
 {
-  return do_assignment_internal (string, 0);
+  WORD_DESC td;
+
+  td.flags = W_ASSIGNMENT;
+  td.word = string;
+
+  do_assignment_internal (&td, 0);
 }
 
 /***************************************************
@@ -2445,6 +2513,14 @@ expand_string_unsplit_to_string (string, quoted)
   return (expand_string_to_string_internal (string, quoted, expand_string_unsplit));
 }
 
+char *
+expand_assignment_string_to_string (string, quoted)
+     char *string;
+     int quoted;
+{
+  return (expand_string_to_string_internal (string, quoted, expand_string_assignment));
+}
+
 #if defined (COND_COMMAND)
 /* Just remove backslashes in STRING.  Returns a new string. */
 char *
@@ -6845,8 +6921,12 @@ finished_with_string:
       list = make_word_list (tword, (WORD_LIST *)NULL);
       if (word->flags & W_ASSIGNMENT)
        tword->flags |= W_ASSIGNMENT;   /* XXX */
+      if (word->flags & W_COMPASSIGN)
+       tword->flags |= W_COMPASSIGN;   /* XXX */
       if (word->flags & W_NOGLOB)
        tword->flags |= W_NOGLOB;       /* XXX */
+      if (word->flags & W_NOEXPAND)
+       tword->flags |= W_NOEXPAND;     /* XXX */
       if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
        tword->flags |= W_QUOTED;
     }
@@ -6872,8 +6952,12 @@ finished_with_string:
            tword->flags |= W_QUOTED;
          if (word->flags & W_ASSIGNMENT)
            tword->flags |= W_ASSIGNMENT;
+         if (word->flags & W_COMPASSIGN)
+           tword->flags |= W_COMPASSIGN;
          if (word->flags & W_NOGLOB)
            tword->flags |= W_NOGLOB;
+         if (word->flags & W_NOEXPAND)
+           tword->flags |= W_NOEXPAND;
        }
     }
 
@@ -7435,6 +7519,31 @@ shell_expand_word_list (tlist, eflags)
 
       next = tlist->next;
 
+#if defined (ARRAY_VARS)
+      /* If this is a compound array assignment to a builtin that accepts
+         such assignments (e.g., `declare'), take the assignment and perform
+         it separately, handling the semantics of declarations inside shell
+         functions.  This avoids the double-evaluation of such arguments,
+         because `declare' does some evaluation of compound assignments on
+         its own. */
+      if ((tlist->word->flags & (W_COMPASSIGN|W_ASSIGNARG)) == (W_COMPASSIGN|W_ASSIGNARG))
+       {
+         int t;
+
+         t = do_word_assignment (tlist->word);
+         if (t == 0)
+           {
+             last_command_exit_value = EXECUTION_FAILURE;
+             exp_jump_to_top_level (DISCARD);
+           }
+
+         /* Now transform the word as ksh93 appears to do and go on */
+         t = assignment (tlist->word->word, 0);
+         tlist->word->word[t] = '\0';
+         tlist->word->flags &= ~(W_ASSIGNMENT|W_NOSPLIT|W_COMPASSIGN|W_ASSIGNARG); 
+       }
+#endif
+
       expanded_something = 0;
       expanded = expand_word_internal
        (tlist->word, 0, 0, &has_dollar_at, &expanded_something);
@@ -7521,7 +7630,7 @@ expand_word_list_internal (list, eflags)
              for (temp_list = subst_assign_varlist; temp_list; temp_list = temp_list->next)
                {
                  this_command_name = (char *)NULL;     /* no arithmetic errors */
-                 tint = do_assignment (temp_list->word->word);
+                 tint = do_word_assignment (temp_list->word);
                  /* Variable assignment errors in non-interactive shells
                     running in Posix.2 mode cause the shell to exit. */
                  if (tint == 0)
@@ -7569,23 +7678,23 @@ expand_word_list_internal (list, eflags)
 
   if ((eflags & WEXP_VARASSIGN) && subst_assign_varlist)
     {
-      sh_assign_func_t *assign_func;
+      sh_wassign_func_t *assign_func;
 
       /* If the remainder of the words expand to nothing, Posix.2 requires
         that the variable and environment assignments affect the shell's
         environment. */
-      assign_func = new_list ? assign_in_env : do_assignment;
+      assign_func = new_list ? assign_in_env : do_word_assignment;
       tempenv_assign_error = 0;
 
       for (temp_list = subst_assign_varlist; temp_list; temp_list = temp_list->next)
        {
          this_command_name = (char *)NULL;
-         tint = (*assign_func) (temp_list->word->word);
+         tint = (*assign_func) (temp_list->word);
          /* Variable assignment errors in non-interactive shells running
             in Posix.2 mode cause the shell to exit. */
          if (tint == 0)
            {
-             if (assign_func == do_assignment)
+             if (assign_func == do_word_assignment)
                {
                  last_command_exit_value = EXECUTION_FAILURE;
                  if (interactive_shell == 0 && posixly_correct)
diff --git a/subst.h b/subst.h
index 7484743dee4eae75799e2133f48e891919faac43..1832c64f6cb0ca3b94d071accfea1e1989995a8e 100644 (file)
--- a/subst.h
+++ b/subst.h
@@ -93,11 +93,12 @@ extern char *strip_trailing_ifs_whitespace __P((char *, char *, int));
 
 /* Given STRING, an assignment string, get the value of the right side
    of the `=', and bind it to the left side.  If EXPAND is true, then
-   perform parameter expansion, command substitution, and arithmetic
-   expansion on the right-hand side.  Perform tilde expansion in any
-   case.  Do not perform word splitting on the result of expansion. */
-extern int do_assignment __P((const char *));
-extern int do_assignment_no_expand __P((const char *));
+   perform tilde expansion, parameter expansion, command substitution,
+   and arithmetic expansion on the right-hand side.  Do not perform word
+   splitting on the result of expansion. */
+extern int do_assignment __P((char *));
+extern int do_assignment_no_expand __P((char *));
+extern int do_word_assignment __P((WORD_DESC *));
 
 /* Append SOURCE to TARGET at INDEX.  SIZE is the current amount
    of space allocated to TARGET.  SOURCE can be NULL, in which
@@ -144,6 +145,7 @@ extern WORD_LIST *expand_string __P((char *, int));
    to a string and deallocating the WORD_LIST *. */
 extern char *expand_string_to_string __P((char *, int));
 extern char *expand_string_unsplit_to_string __P((char *, int));
+extern char *expand_assignment_string_to_string __P((char *, int));
 
 /* De-quoted quoted characters in STRING. */
 extern char *dequote_string __P((char *));
index 72ec06a2c1fd8dde92acea5e8ac773e35f1d061b..3efcf32d68e9722024b6ca9d67f9e81b2aa5ac04 100755 (executable)
@@ -1,4 +1,4 @@
-BUILD_DIR=/usr/local/build/bash/bash-current
+BUILD_DIR=/usr/local/build/chet/bash/bash-current
 THIS_SH=$BUILD_DIR/bash
 PATH=$PATH:$BUILD_DIR
 
diff --git a/tests/extglob3.right b/tests/extglob3.right
new file mode 100644 (file)
index 0000000..f677f96
--- /dev/null
@@ -0,0 +1,26 @@
+match 1
+match 2
+match 3
+match 4
+match 1a
+match 1b
+match 2a
+match 2b
+match 3a
+match 3b
+match 4a
+match 4b
+match 5
+match 6
+match 7
+match 8
+match 9
+match 10
+match 11
+match 12
+match 13
+match 14
+match 15
+match 16
+match 17
+match 18
diff --git a/tests/extglob3.tests b/tests/extglob3.tests
new file mode 100644 (file)
index 0000000..e77edd2
--- /dev/null
@@ -0,0 +1,53 @@
+shopt -s extglob
+
+[[ ab/../ == @(ab|+([^/]))/..?(/) ]] && echo match 1
+
+[[ ab/../ == +([^/])/..?(/) ]] && echo match 2
+
+[[ ab/../ == @(ab|?b)/..?(/) ]] && echo match 3
+
+[[ ab/../ == +([^/])/../ ]] && echo match 4
+
+[[ ab/../ == +([!/])/..?(/) ]] && echo match 1a
+
+[[ ab/../ == @(ab|+([!/]))/..?(/) ]] && echo match 1b
+
+[[ ab/../ == +([!/])/../ ]] && echo match 2a
+
+[[ ab/../ == +([!/])/..?(/) ]] && echo match 2b
+
+[[ ab/../ == +([!/])/..@(/) ]] && echo match 3a
+
+[[ ab/../ == +(ab)/..?(/) ]] && echo match 3b
+
+[[ ab/../ == [!/][!/]/../ ]] && echo match 4a
+
+[[ ab/../ == @(ab|?b)/..?(/) ]] && echo match 4b
+
+[[ ab/../ == [^/][^/]/../ ]] && echo match 5
+
+[[ ab/../ == ?b/..?(/) ]] && echo match 6
+
+[[ ab/../ == +(?b)/..?(/) ]] && echo match 7
+
+[[ ab/../ == +(?b|?b)/..?(/) ]] && echo match 8
+
+[[ ab/../ == @(?b|?b)/..?(/) ]] && echo match 9
+
+[[ ab/../ == @(a?|?b)/..?(/) ]] && echo match 10
+
+[[ ab/../ == ?(ab)/..?(/) ]] && echo match 11
+
+[[ ab/../ == ?(ab|??)/..?(/) ]] && echo match 12
+
+[[ ab/../ == @(??)/..?(/) ]] && echo match 13
+
+[[ ab/../ == @(??|a*)/..?(/) ]] && echo match 14
+
+[[ ab/../ == @(a*)/..?(/) ]] && echo match 15
+
+[[ ab/../ == +(??)/..?(/) ]] && echo match 16
+
+[[ ab/../ == +(??|a*)/..?(/) ]] && echo match 17
+
+[[ ab/../ == +(a*)/..?(/) ]] && echo match 18
diff --git a/tests/run-extglob3 b/tests/run-extglob3
new file mode 100644 (file)
index 0000000..2675196
--- /dev/null
@@ -0,0 +1,4 @@
+PATH=$PATH:`pwd`
+export PATH
+${THIS_SH} ./extglob3.tests > /tmp/xx
+diff /tmp/xx extglob3.right && rm -f /tmp/xx
index ecb7e9a2539900a4a8e5a1b926a27484a07fdefd..b8569c11cd60a3b820a9275628467a3b0d15de61 100644 (file)
@@ -1,2 +1,2 @@
-${THIS_SH} ./tilde-tests > /tmp/xx
+${THIS_SH} ./tilde.tests > /tmp/xx
 diff /tmp/xx tilde.right && rm -f /tmp/xx
diff --git a/tests/run-tilde2 b/tests/run-tilde2
new file mode 100644 (file)
index 0000000..4446989
--- /dev/null
@@ -0,0 +1,2 @@
+${THIS_SH} ./tilde2.tests > /tmp/xx
+diff /tmp/xx tilde2.right && rm -f /tmp/xx
diff --git a/tests/tilde.tests b/tests/tilde.tests
new file mode 100644 (file)
index 0000000..f5f5309
--- /dev/null
@@ -0,0 +1,66 @@
+# this is needed because posix mode restricts tilde expansion to assignment
+# statements preceding a command, instead of the default of expanding all
+# assignment statements on the line (e.g., after `export').  Without this,
+# the next-to-last test fails
+set +o posix
+
+HOME=/usr/xyz
+SHELL=~/bash
+echo ~ch\et
+echo ~/"foo"
+echo "~chet"/"foo"
+echo \~chet/"foo"
+echo \~chet/bar
+echo ~\chet/bar
+echo ~chet""/bar
+echo ":~chet/"
+echo abcd~chet
+echo "SHELL=~/bash"
+echo $SHELL
+echo abcd:~chet
+path=/usr/ucb:/bin:~/bin:~/tmp/bin:/usr/bin
+echo $path
+
+cd /usr
+cd /tmp
+echo ~-
+echo ~+
+
+XPATH=/bin:/usr/bin:.
+
+# yes tilde expansion
+PPATH=$XPATH:~/bin
+echo "$PPATH"
+
+# no tilde expansion
+PPATH="$XPATH:~/bin"
+echo "$PPATH"
+
+# yes tilde expansion
+export PPATH=$XPATH:~/bin
+echo "$PPATH"
+declare -x PPATH=$XPATH:~/bin
+echo "$PPATH"
+
+# no tilde expansion
+export PPATH="$XPATH:~/bin"
+echo "$PPATH"
+declare -x PPATH="$XPATH:~/bin"
+echo "$PPATH"
+
+# more tests of tilde expansion when executing case commands
+case ~ in
+$HOME) echo ok 1;;
+*) echo bad 1 ;;
+esac
+
+case ~ in
+~)     echo ok 2 ;;
+\~)    echo bad 2a ;;
+*)     echo bad 2b ;;
+esac
+
+case $unset in
+"")    echo ok 3 ;;
+*)     echo bad 3 ;;
+esac
diff --git a/tests/tilde2.right b/tests/tilde2.right
new file mode 100644 (file)
index 0000000..90897fc
--- /dev/null
@@ -0,0 +1,17 @@
+PATH=~/bin:/bin:/usr/bin:.
+/usr/xyz/bin:~/bin2:/bin:/usr/bin:.
+PATH=~/bin:~/bin2:/bin:/usr/bin:.
+~/bin
+~
+/usr/xyz
+~
+~
+~
+argv[1] = <\a>
+argv[1] = <\a>
+/usr/xyz/bash
+ok
+~
+~
+make -k FOO=/usr/xyz/mumble
+/usr/xyz/mumble
diff --git a/tests/tilde2.tests b/tests/tilde2.tests
new file mode 100644 (file)
index 0000000..3e2464f
--- /dev/null
@@ -0,0 +1,46 @@
+HOME=/usr/xyz
+XPATH=/bin:/usr/bin:.
+
+ADDPATH=PATH=~/bin:$XPATH
+
+echo $ADDPATH
+
+unset ADDPATH
+: ${ADDPATH:=~/bin:~/bin2:$XPATH}
+echo $ADDPATH
+
+unset ADDPATH
+: ${ADDPATH:=PATH=~/bin:~/bin2:$XPATH}
+echo $ADDPATH
+
+cat << !
+~/bin
+!
+
+echo "~"
+
+echo ${TPATH:-~}
+echo "${TPATH:-~}"
+echo "${TPATH:-"~"}"
+
+echo "${XPATH+~}"
+
+recho "\a"
+recho "${TPATH:-\a}"
+
+SHELL=~/bash
+echo $SHELL
+
+case $SHELL in
+~/bash)        echo ok;;
+*)     echo bad;;
+esac
+
+somevar=
+echo "${somevar:-~}"
+echo "${somevar:-"~"}"
+
+echo make -k FOO=~/mumble
+
+typeset FOO=~/mumble
+echo "$FOO"
index 7d4d930927132ac8eaf609a70032869f832321d9..92717584380c1f79c04e0701d02a48d7712a0cb2 100644 (file)
@@ -320,7 +320,7 @@ initialize_shell_variables (env, privmode)
 #if defined (ARRAY_VARS)
 #  if 0
       /* Array variables may not yet be exported. */
-      else if (*string == '(' && string[1] == '[' && xstrchr (string, ')'))
+      else if (*string == '(' && string[1] == '[' && string[strlen (string) - 1] == ')')
        {
          string_length = 1;
          temp_string = extract_array_assignment_list (string, &string_length);
@@ -1228,7 +1228,14 @@ get_bash_command (var)
 {
   char *p;
 
-  p = savestring (the_printed_command_except_trap);
+  
+  if (the_printed_command_except_trap)
+    p = savestring (the_printed_command_except_trap);
+  else
+    {
+      p = (char *)xmalloc (1);
+      p[0] = '\0';
+    }
   FREE (value_cell (var));
   var_setvalue (var, p);
   return (var);
@@ -2067,12 +2074,15 @@ bind_function_def (name, value)
    responsible for moving the main temporary env to one of the other
    temporary environments.  The expansion code in subst.c calls this. */
 int
-assign_in_env (string)
-     const char *string;
+assign_in_env (word)
+     WORD_DESC *word;
 {
   int offset;
   char *name, *temp, *value;
   SHELL_VAR *var;
+  const char *string;
+
+  string = word->word;
 
   offset = assignment (string, 0);
   name = savestring (string);
@@ -2092,10 +2102,13 @@ assign_in_env (string)
        }
 
       temp = name + offset + 1;
+#if 0
       temp = (xstrchr (temp, '~') != 0) ? bash_tilde_expand (temp, 1) : savestring (temp);
-
       value = expand_string_unsplit_to_string (temp, 0);
       free (temp);
+#else
+      value = expand_assignment_string_to_string (temp, 0);
+#endif
     }
 
   if (temporary_env == 0)
index cd11fd97c8961fa6b5d56c79e623d1f718738099..08db0f5e3b042a00737f957edde23e147291a84f 100644 (file)
@@ -256,7 +256,8 @@ extern SHELL_VAR *bind_variable_value __P((SHELL_VAR *, char *));
 extern SHELL_VAR *bind_int_variable __P((char *, char *));
 extern SHELL_VAR *bind_var_to_int __P((char *, intmax_t));
 
-extern int assign_in_env __P((const char *));
+extern int assign_in_env __P((WORD_DESC *));
+
 extern int unbind_variable __P((const char *));
 extern int unbind_func __P((const char *));
 extern int unbind_function_def __P((const char *));