(push_index) that caused the 511th character in the buffer to be
discarded. Fixes bug reported by Tom Bjorkholm <tom.bjorkholm@ericsson.com>
- 5/5
+ 5/8
---
-print_cmd.c
- - added logic (inside_pipeline variable) to print_connection code and
- print_redirection to handle the case of a command with a here
- document inside a pipeline. In that case, print_redirection prints
- the `|' before the here document text, so the parser knows the
- command is continued. Fixes problem with exporting functions with
- pipelines like this reported by Chris Lesner <chris.lesner@gmail.com>
+subst.c
+ - fix parameter_brace_remove_pattern to pass getpattern() newly-allocated
+ memory. If word expansions (particularly brace expansions) are
+ required, the expansion code will free the string passed to
+ expand_word_internal, and we don't want to free unallocated memory
+ (patstr++) or have duplicate frees (patstr)
+
+ 5/9
+ ---
+lib/readline/signals.c
+ - fix bug in rl_set_signals that caught SIGINT twice and didn't catch
+ SIGTERM. Bug reported by Ed Kwan <ed.kwan@onstor.com>
tests/cond-regexp.sub f
tests/cprint.tests f
tests/cprint.right f
+tests/cprint1.sub f
tests/dbg-support.right f
tests/dbg-support.sub f
tests/dbg-support.tests f
tests/nquote3.right f
tests/nquote4.tests f
tests/nquote4.right f
+tests/nquote5.tests f
+tests/nquote5.right f
tests/posix2.tests f
tests/posix2.right f
tests/posixpat.tests f
tests/run-nquote2 f
tests/run-nquote3 f
tests/run-nquote4 f
+tests/run-nquote5 f
tests/run-posix2 f
tests/run-posixpat f
tests/run-precedence f
precedence as \fB==\fP and \fB!=\fP.
When it is used, the string to the right of the operator is considered
an extended regular expression and matched accordingly (as in \fIregex\fP(3)).
-The return value is 0 if the string matches
-the pattern, and 1 otherwise.
+Any part of the pattern may be quoted to force it to be matched as a
+string.
+The return value is 0 if the string matches the pattern, and 1 otherwise.
If the regular expression is syntactically incorrect, the conditional
expression's return value is 2.
If the shell option
.\" MAN PAGE COMMENTS to
.\"
.\" Chet Ramey
-.\" Information Network Services
.\" Case Western Reserve University
.\" chet@po.cwru.edu
.\"
-.\" Last Change: Fri Jan 12 16:29:22 EST 2007
+.\" Last Change: Tue May 1 10:05:17 EDT 2007
.\"
.\" bash_builtins, strip all but Built-Ins section
.if \n(zZ=1 .ig zZ
.if \n(zY=1 .ig zY
-.TH BASH 1 "2007 January 12" "GNU Bash-3.2"
+.TH BASH 1 "2007 May 1" "GNU Bash-3.2"
.\"
.\" There's some problem with having a `@'
.\" in a tagged paragraph with the BSD man macros.
[options]
[file]
.SH COPYRIGHT
-.if n Bash is Copyright (C) 1989-2005 by the Free Software Foundation, Inc.
-.if t Bash is Copyright \(co 1989-2005 by the Free Software Foundation, Inc.
+.if n Bash is Copyright (C) 1989-2007 by the Free Software Foundation, Inc.
+.if t Bash is Copyright \(co 1989-2007 by the Free Software Foundation, Inc.
.SH DESCRIPTION
.B Bash
is an \fBsh\fR-compatible command language interpreter that
Note that unlike the metacharacters \fB(\fP and \fB)\fP, \fB{\fP and
\fB}\fP are \fIreserved words\fP and must occur where a reserved
word is permitted to be recognized. Since they do not cause a word
-break, they must be separated from \fIlist\fP by whitespace.
+break, they must be separated from \fIlist\fP by whitespace or another
+shell metacharacter.
.TP
((\fIexpression\fP))
The \fIexpression\fP is evaluated according to the rules described
pathname expansion.
\fIParameter\fP is expanded and the longest match of \fIpattern\fP
against its value is replaced with \fIstring\fP.
-If \Ipattern\fP begins with \fB/\fP, all matches of \fIpattern\fP are
+If \fIpattern\fP begins with \fB/\fP, all matches of \fIpattern\fP are
replaced with \fIstring\fP. Normally only the first match is replaced.
If \fIpattern\fP begins with \fB#\fP, it must match at the beginning
of the expanded value of \fIparameter\fP.
.if n .sp 1
Expressions may be combined using the following operators, listed
in decreasing order of precedence.
+The evaluation depends on the number of arguments; see below.
.RS
.PD 0
.TP
.BR "CONDITIONAL EXPRESSIONS" ,
the result of the expression is the result of the binary test using
the first and third arguments as operands.
+The \fB\-a\fP and \fB\-o\fP operators are considered binary operators
+when there are three arguments.
If the first argument is \fB!\fP, the value is the negation of
the two-argument test using the second and third arguments.
If the first argument is exactly \fB(\fP and the third argument is
exactly \fB)\fP, the result is the one-argument test of the second
argument.
Otherwise, the expression is false.
-The \fB\-a\fP and \fB\-o\fP operators are considered binary operators
-in this case.
.TP
4 arguments
If the first argument is \fB!\fP, the result is the negation of
of alphabetic characters.
The return value is 0 if the string matches (@samp{==}) or does not
match (@samp{!=})the pattern, and 1 otherwise.
-Any part of the pattern may be quoted to force it to be matched as a
-string.
+Any part of the pattern may be quoted to force it to be matched as a string.
An additional binary operator, @samp{=~}, is available, with the same
precedence as @samp{==} and @samp{!=}.
When it is used, the string to the right of the operator is considered
an extended regular expression and matched accordingly (as in @i{regex}3)).
+Any part of the pattern may be quoted to force it to be matched as a string.
The return value is 0 if the string matches
the pattern, and 1 otherwise.
If the regular expression is syntactically incorrect, the conditional
In addition to the creation of a subshell, there is a subtle difference
between these two constructs due to historical reasons. The braces
are @code{reserved words}, so they must be separated from the @var{list}
-by @code{blank}s. The parentheses are @code{operators}, and are
+by @code{blank}s or other shell metacharacters.
+The parentheses are @code{operators}, and are
recognized as separate tokens by the shell even if they are not separated
from the @var{list} by whitespace.
that surround the body of the function must be separated from the body by
@code{blank}s or newlines.
This is because the braces are reserved words and are only recognized
-as such when they are separated by whitespace.
+as such when they are separated from the command list
+by whitespace or another shell metacharacter.
Also, when using the braces, the @var{list} must be terminated by a semicolon,
a @samp{&}, or a newline.
Expressions may be combined using the following operators, listed in
decreasing order of precedence.
+The evaluation depends on the number of arguments; see below.
@table @code
@item ! @var{expr}
operators (@pxref{Bash Conditional Expressions}), the
result of the expression is the result of the binary test using the
first and third arguments as operands.
+The @samp{-a} and @samp{-o} operators are considered binary operators
+when there are three arguments.
If the first argument is @samp{!}, the value is the negation of
the two-argument test using the second and third arguments.
If the first argument is exactly @samp{(} and the third argument is
exactly @samp{)}, the result is the one-argument test of the second
argument.
Otherwise, the expression is false.
-The @samp{-a} and @samp{-o} operators are considered binary operators
-in this case.
@item 4 arguments
If the first argument is @samp{!}, the result is the negation of
entry displayed by the @code{history} builtin.
If this variable is set, time stamps are written to the history file so
they may be preserved across shell sessions.
+This uses the history comment character to distinguish timestamps from
+other history lines.
@item HOSTFILE
Contains the name of a file in the same format as @file{/etc/hosts} that
Copyright (C) 1988-2007 Free Software Foundation, Inc.
@end ignore
-@set LASTCHANGE Tue May 1 10:05:36 EDT 2007
+@set LASTCHANGE Mon May 14 10:02:55 EDT 2007
@set EDITION 3.2
@set VERSION 3.2
-@set UPDATED 1 May 2007
+@set UPDATED 14 May 2007
@set UPDATED-MONTH May 2007
@ignore
-Copyright (C) 1988-2006 Free Software Foundation, Inc.
+Copyright (C) 1988-2007 Free Software Foundation, Inc.
@end ignore
-@set LASTCHANGE Sat Dec 30 19:31:54 EST 2006
+@set LASTCHANGE Tue May 1 10:05:36 EDT 2007
@set EDITION 3.2
@set VERSION 3.2
-@set UPDATED 30 December 2006
-@set UPDATED-MONTH December 2006
+@set UPDATED 1 May 2007
+@set UPDATED-MONTH May 2007
sigemptyset (&bset);
sigaddset (&bset, SIGINT);
- sigaddset (&bset, SIGINT);
+ sigaddset (&bset, SIGTERM);
#if defined (SIGQUIT)
sigaddset (&bset, SIGQUIT);
#endif
/* Non-zero means the stuff being printed is inside of a function def. */
static int inside_function_def;
-
-/* Used to decide where to put the `|' if the command in the pipeline has
- here documents associated with it. If non-zero, print_redirection
- prints the `|' before the text of the here document and print_connection
- suppresses the `|'. */
-static int inside_pipeline;
static int skip_this_indent;
-
-/* Flag indicating we printed a here-document. */
static int was_heredoc;
/* The depth of the group commands that we are currently printing. This
make_command_string (command)
COMMAND *command;
{
- command_string_index = was_heredoc = inside_pipeline = 0;
+ command_string_index = was_heredoc = 0;
make_command_string_internal (command);
return (the_printed_command);
}
case cm_connection:
skip_this_indent++;
- if (command->value.Connection->connector == '|')
- inside_pipeline = 1;
make_command_string_internal (command->value.Connection->first);
- if (command->value.Connection->connector == '|')
- inside_pipeline = 0;
switch (command->value.Connection->connector)
{
case '|':
{
char c = command->value.Connection->connector;
- if (c == '&' || was_heredoc == 0)
- cprintf (" %c", c);
- else
- was_heredoc = 0;
+ cprintf (" %c", c);
if (c != '&' || command->value.Connection->second)
{
cprintf (" ");
print the here documents. */
if (heredocs)
{
-if (inside_pipeline)
-{
-itrace("print_redirection_list: here documents inside pipeline");
-}
cprintf (" ");
for (hdtail = heredocs; hdtail; hdtail = hdtail->next)
{
{
int kill_leading, redirector, redir_fd;
WORD_DESC *redirectee;
- char *x;
kill_leading = 0;
redirectee = redirect->redirectee.filename;
if (redirector != 0)
cprintf ("%d", redirector);
/* If the here document delimiter is quoted, single-quote it. */
- x = (redirect->redirectee.filename->flags & W_QUOTED)
- ? sh_single_quote (redirect->here_doc_eof)
- : redirect->here_doc_eof;
- cprintf ("<<%s%s", kill_leading? "-" : "", x);
- if (x != redirect->here_doc_eof)
- free (x);
-if (inside_pipeline)
- cprintf (" |");
- cprintf ("\n");
- cprintf ("%s%s", redirect->redirectee.filename->word, redirect->here_doc_eof);
+ if (redirect->redirectee.filename->flags & W_QUOTED)
+ {
+ char *x;
+ x = sh_single_quote (redirect->here_doc_eof);
+ cprintf ("<<%s%s\n", kill_leading? "-" : "", x);
+ free (x);
+ }
+ else
+ cprintf ("<<%s%s\n", kill_leading? "-" : "", redirect->here_doc_eof);
+ cprintf ("%s%s",
+ redirect->redirectee.filename->word, redirect->here_doc_eof);
break;
case r_reading_string:
{
inside_function_def = 0;
indentation = 0;
- inside_pipeline = 0;
}
static void
inside_function_def++;
indentation += indentation_amount;
- cmdcopy = copy_command (func->command); /* possible mem leak on unwind-protect */
+ cmdcopy = copy_command (func->command);
if (cmdcopy->type == cm_group)
{
func_redirects = cmdcopy->redirects;
old_indent = indentation;
old_amount = indentation_amount;
command_string_index = was_heredoc = 0;
- inside_pipeline = 0;
if (name && *name)
cprintf ("%s ", name);
if (patspec == RP_LONG_LEFT || patspec == RP_LONG_RIGHT)
patstr++;
- pattern = getpattern (patstr, quoted, 1);
+ /* Need to pass getpattern newly-allocated memory in case of expansion --
+ the expansion code will free the passed string on an error. */
+ temp1 = savestring (patstr);
+ pattern = getpattern (temp1, quoted, 1);
+ free (temp1);
temp1 = (char *)NULL; /* shut up gcc */
switch (vtype)
int t_index, sindex, c, tflag;
intmax_t number;
- value = (char *)NULL;
+ temp = temp1 = value = (char *)NULL;
var_is_set = var_is_null = var_is_special = check_nullness = 0;
want_substring = want_indir = want_patsub = 0;
temp = (char *)NULL;
goto bad_substitution;
}
-
/* Indirect expansion begins with a `!'. A valid indirect expansion is
either a variable name, one of the positional parameters or a special
variable that expands to one of the positional parameters. */
{
echo abcde
}
+a is a function
+a ()
+{
+ cat <<-'+'
+ cat - | utkSort
+ itkSchemaToColumnType
+ atkCacheToColumnType \"$npName\" | atkActiveTableLineSelect
+| utkSort
+ atkCacheToColumnType \"$npName\" |
+atkTransactionTableLineSelect | utkSort
+ itkDirToColumnType \"$dirName\" | atkActiveTableLineSelect |
+utkSort
+ itkDirToColumnType \"$dirName\" | atkActiveTableLineSelect |
+utkSort
++
+ | tr "\t" " " | tr -s " "
+}
+b is a function
+b ()
+{
+ cat /etc/passwd | cat - <<-'+'
+more
+passwords
+from
+the
+file
++
+ | tr -s " "
+}
+c is a function
+c ()
+{
+ cat /etc/passwd | tr -s " " | cat - <<-'+'
+more
+passwords
+from
+the
+file
++
+ | cat - <<-'foo'
+last
+bunch
+of
+words
+foo
+
+}
type tf2
tf
+
+${THIS_SH} ./cprint1.sub
--- /dev/null
+#
+# a nonsense script and shell function to test out the command printing code
+#
+tf()
+{
+ # simple command with redir
+ echo this is ${0##*/} > /dev/null
+
+ # pipeline
+ echo a | cat - > /dev/null
+
+ test -f ${0##*/} && echo ${0##*/} is a regular file
+ test -d ${0##*/} || echo ${0##*/} is not a directory
+
+ echo a ; echo b ; echo c
+
+ echo background >/dev/null &
+
+ ( exit 1 )
+ echo $?
+
+ { echo a ; }
+
+ i=0
+ while (( i < 3 )); do
+ test -r /dev/fd/$i
+ i=$(( i + 1 ))
+ done
+
+ [[ -r /dev/fd/0 && -w /dev/fd/1 ]] || echo oops > /dev/null
+
+ for name in $( echo 1 2 3 ); do
+ test -r /dev/fd/$name
+ done
+
+ if [[ -r /dev/fd/0 && -w /dev/fd/1 ]] ; then
+ echo ok > /dev/null
+ elif (( 7 > 40 )) ; then
+ echo oops
+ else
+ echo done
+ fi > /dev/null
+
+ case $PATH in
+ *$PWD*) echo \$PWD in \$PATH ;;
+ *) echo \$PWD not in \$PATH ;;
+ esac > /dev/null
+
+ while false; do echo z; done > /dev/null
+
+ until true; do echo z ; done > /dev/null
+
+ echo \&\|'()' \{ echo abcde \; \}
+ # when not in POSIX mode, we can have weirdly-named functions
+ eval fu\%nc'()' \{ echo abcde \; \}
+ type fu\%nc
+}
+
+tf2()
+{
+ ( { time -p echo a | cat - > /dev/null ; } ) 2>&1
+}
+
+type tf
+type tf2
+
+tf
--- /dev/null
+a()
+{
+ cat <<-'+' | tr "\t" " " | tr -s " "
+ cat - | utkSort
+ itkSchemaToColumnType
+ atkCacheToColumnType \"$npName\" | atkActiveTableLineSelect
+| utkSort
+ atkCacheToColumnType \"$npName\" |
+atkTransactionTableLineSelect | utkSort
+ itkDirToColumnType \"$dirName\" | atkActiveTableLineSelect |
+utkSort
+ itkDirToColumnType \"$dirName\" | atkActiveTableLineSelect |
+utkSort
+ +
+}
+
+type a
+
+b()
+{
+ cat /etc/passwd | cat - <<-'+' | tr -s " "
+ more
+ passwords
+ from
+ the
+ file
+ +
+}
+
+type b
+
+c()
+{
+ cat /etc/passwd | tr -s " " | cat - <<-'+' | cat - <<-'foo'
+ more
+ passwords
+ from
+ the
+ file
+ +
+last
+bunch
+of
+words
+foo
+}
+
+type c