doc/bashref.texi
- update posix mode section with change to unset for interp 1009
+
+ 12/1
+ ----
+lib/readline/readline.c
+ - _rl_subseq_result: add check before _rl_do_lowercase_version that
+ _rl_to_lower actually results in a different key sequence
+ Report and patch from Grisha Levit <grishalevit@gmail.com>
+
+lib/readline/isearch.c
+ - _rl_isearch_dispatch: if the function bound to a key and the function
+ bound to the result of _rl_to_lower for that key are both
+ rl_do_lowercase_version, just insert the key into the search string
+
+ 12/5
+ ----
+parse.y,parser.h
+ - heredoc_string: new variable to indicate whether or not we're reading
+ a here-document from an alias (a pushed string). Set in
+ gather_here_documents individually for each call to
+ make_here_document.
+
+parse.y
+ - read_a_line: if heredoc_string is non-zero, use shell_getc instead
+ of yy_getc to get the right alias processing
+ - shell_getc: if heredoc_string is non-zero, don't add a space to the
+ end of the alias -- it can mess up the here-document delimiter if
+ the next character is a newline
+ Report and sample patch from gldrk <me@rarity.fan>
+
+parse.y,make_cmd.c
+ - read_a_line,make_here_document: if we're using shell_getc to read
+ the body of a here-document, let it manage line_number
tests/heredoc7.sub f
tests/heredoc8.sub f
tests/heredoc9.sub f
+tests/heredoc10.sub f
tests/herestr.tests f
tests/herestr.right f
tests/herestr1.sub f
{
f = cxt->keymap[c].function;
if (f == rl_do_lowercase_version)
- f = cxt->keymap[_rl_to_lower (c)].function;
+ {
+ f = cxt->keymap[_rl_to_lower (c)].function;
+ if (f == rl_do_lowercase_version)
+ f = rl_insert;
+ }
}
if (f == rl_reverse_search_history)
type = m[ANYOTHERKEY].type;
func = m[ANYOTHERKEY].function;
if (type == ISFUNC && func == rl_do_lowercase_version)
- r = _rl_dispatch (_rl_to_lower ((unsigned char)key), map);
+ {
+ int newkey = _rl_to_lower ((unsigned char)key);
+ /* check that there is actually a lowercase version to avoid infinite recursion */
+ r = (newkey != key) ? _rl_dispatch (newkey, map) : 1;
+ }
else if (type == ISFUNC)
{
/* If we shadowed a function, whatever it is, we somehow need a
here_doc_first_line = 0;
line = full_line;
- line_number++;
+
+ /* if read_secondary_line uses shell_getc, that handles incrementing
+ line_number where necessary. */
+ if (heredoc_string == 0)
+ line_number++;
/* If set -v is in effect, echo the line read. read_secondary_line/
read_a_line leaves the newline at the end, so don't print another. */
static REDIRECT *redir_stack[HEREDOC_MAX];
int need_here_doc;
+/* Are we reading a here-document from a string? (alias) */
+int heredoc_string;
+
/* Where shell input comes from. History expansion is performed on each
line when the shell is interactive. */
static char *shell_input_line = (char *)NULL;
/* Allow immediate exit if interrupted during input. */
QUIT;
- c = yy_getc ();
+ /* If we're reading the here-document from an alias, use shell_getc */
+ c = heredoc_string ? shell_getc (0) : yy_getc ();
/* Ignore null bytes in input. */
if (c == 0)
if (interactive && bash_input.type == st_stream)
clearerr (stdin);
if (indx == 0)
- return ((char *)NULL);
+ {
+ /* if we use shell_getc, that increments line_number on eof */
+ if (heredoc_string)
+ line_number--;
+
+ return ((char *)NULL);
+ }
c = '\n';
}
else if (c == '\\' && remove_quoted_newline)
{
QUIT;
- peekc = yy_getc ();
+ /* If we're reading the here-document from an alias, use shell_getc */
+ peekc = heredoc_string ? shell_getc (0) : yy_getc ();
if (peekc == '\n')
{
- line_number++;
+ if (heredoc_string == 0)
+ line_number++;
continue; /* Make the unquoted \<newline> pair disappear. */
}
else if (peekc == EOF)
}
else
{
- yy_ungetc (peekc);
+ if (heredoc_string)
+ shell_ungetc (peekc);
+ else
+ yy_ungetc (peekc);
+
pass_next = 1;
line_buffer[indx++] = c; /* Preserve the backslash. */
}
return the space that will delimit the token and postpone the pop_string.
This set of conditions duplicates what used to be in mk_alexpansion ()
below, with the addition that we don't add a space if we're currently
- reading a quoted string or in a shell comment. */
+ reading a quoted string or in a shell comment or here-document. */
#ifndef OLD_ALIAS_HACK
if (uc == 0 && pushed_string_list && pushed_string_list->flags != PSH_SOURCE &&
pushed_string_list->flags != PSH_DPAREN &&
(parser_state & PST_COMMENT) == 0 &&
(parser_state & PST_ENDALIAS) == 0 && /* only once */
+ heredoc_string == 0 &&
shell_input_line_index > 0 &&
shellblank (shell_input_line[shell_input_line_index-1]) == 0 &&
shell_input_line[shell_input_line_index-1] != '\n' &&
while (need_here_doc > 0)
{
parser_state |= PST_HEREDOC;
+ heredoc_string = expanding_alias () && (shell_input_line_index < shell_input_line_len);
make_here_document (redir_stack[r++], line_number);
parser_state &= ~PST_HEREDOC;
need_here_doc--;
extern int current_token;
extern int parser_state;
extern int need_here_doc;
+extern int heredoc_string;
extern int ignoreeof;
extern int eof_encountered;
"Project-Id-Version: bash 5.2-rc1\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-01-11 14:50-0500\n"
-"PO-Revision-Date: 2023-01-12 14:27-0300\n"
+"PO-Revision-Date: 2023-12-04 14:27-0300\n"
"Last-Translator: Rafael Fontenelle <rafaelff@gnome.org>\n"
"Language-Team: Brazilian Portuguese <ldpbr-translation@lists.sourceforge.net>\n"
"Language: pt_BR\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1)\n"
-"X-Generator: Gtranslator 42.0\n"
+"X-Generator: Gtranslator 45.2\n"
"X-Bugs: Report translation errors to the Language-Team address.\n"
#: arrayfunc.c:66
echo 3 4;
done
}
+hello
+world
+hello
+world
+here-document
+here-document
comsub here-string
-./heredoc.tests: line 181: warning: here-document at line 178 delimited by end-of-file (wanted `')
+./heredoc.tests: line 184: warning: here-document at line 181 delimited by end-of-file (wanted `')
hi
there
''
# various tests for printing here-documents in function bodies
${THIS_SH} ./heredoc9.sub
+# test various combinations of here-documents and aliases
+${THIS_SH} ./heredoc10.sub
+
echo $(
cat <<< "comsub here-string"
)
--- /dev/null
+# This program 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 3 of the License, or
+# (at your option) any later version.
+#
+# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+# test various forms of reading here-documents from an alias
+shopt -s expand_aliases
+
+# single alias definition contains entire here-document
+alias 'foo=cat <<EOF
+hello
+world
+EOF'
+foo
+
+# here-document body continues after alias definition
+alias 'foo=cat <<EOF
+hello'
+foo
+world
+EOF
+
+# here-document delimiter in one alias, body in another
+shopt -s expand_aliases
+alias c='cat <<\END' d='c
+here-document
+END'
+d
+
+# make sure delimiter is recognized whether the alias ends with a newline or not
+shopt -s expand_aliases
+alias c='cat <<\END' d='c
+here-document
+END
+'
+d
30
40
50
+declare -x var="60"
+outside
+assignment
|0|10|
10
|0|10|
outside 2.1: var=global
inside func1: var=value
outside 3.0: var=value
+inside func1: var=func
+outside 3.5: var=outside
inside func2: var=global
outside 4.0: var=outside
foo: hello world
echo expect 50
var=50 command printenv var
+
+# this behaves the same in bash and posix mode
+export -n var # make sure it's not exported
+echo expect 60
+var=60 export var
+declare -p var
+
+# this behaves differently in bash and posix mode: `.' is a special builtin
+unset -v var
+var=outside
+echo 'var=assignment' >$TMPFILE
+
+echo expect outside
+var=temp . $TMPFILE
+echo $var
+
+set -o posix
+echo expect assignment
+var=temp . $TMPFILE
+echo $var
+
+rm -f $TMPFILE
+unset -v var
unset -v var
unset -f func1
+# operations inside a function on temporary variables do not propagate
+func1()
+{
+ export var
+ echo -n 'inside func1: ' ; echo "var=${var-<unset>}"
+}
+var=outside
+var=func func1
+echo -n 'outside 3.5: ' ; echo "var=${var-<unset>}"
+
+unset -v var
+unset -f func1
+
func2()
{
local var=local