]> git.ipfire.org Git - thirdparty/bash.git/commitdiff
readline fix for do-lowercase-version; fix for reading here-documents from aliases
authorChet Ramey <chet.ramey@case.edu>
Tue, 5 Dec 2023 16:54:24 +0000 (11:54 -0500)
committerChet Ramey <chet.ramey@case.edu>
Tue, 5 Dec 2023 16:54:24 +0000 (11:54 -0500)
15 files changed:
CWRU/CWRU.chlog
MANIFEST
lib/readline/isearch.c
lib/readline/readline.c
make_cmd.c
parse.y
parser.h
po/pt_BR.gmo
po/pt_BR.po
tests/heredoc.right
tests/heredoc.tests
tests/heredoc10.sub [new file with mode: 0644]
tests/varenv.right
tests/varenv1.sub
tests/varenv12.sub

index baf1677b8bd682b2722ec87d601873d4b09f36c2..c163e28a60da20a13229e162e8d331e25417d0ac 100644 (file)
@@ -8109,3 +8109,35 @@ builtins/set.def
 
 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
index c6c4817cd0deea02bc5cf6542a1bcfde2a1ac7d2..81ef5098992f440195d6fa7aa6d87f7fbb25cf45 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -1246,6 +1246,7 @@ tests/heredoc6.sub        f
 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
index 07e76f1165e611ad54feaf7ce3b1d9b3ea76b480..9ddf9ce3355d11cf45999b45de77f80b61579e4d 100644 (file)
@@ -430,7 +430,11 @@ add_character:
        {
          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)
index 608c65ec3758076aa166652d031b93067e427dc7..dbe57ef6d73b593713a119796977af9377613e03 100644 (file)
@@ -1124,7 +1124,11 @@ _rl_subseq_result (int r, Keymap map, int key, int got_subseq)
       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
index db4f37599455a6896a6fcd9f6b98809a9be4464e..3830a3b22b708807d4e5c132cd5ea55178ccc3ef 100644 (file)
@@ -573,7 +573,11 @@ make_here_document (REDIRECT *temp, int lineno)
 
       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. */
diff --git a/parse.y b/parse.y
index 4170d144b43993a70ce53a0d5ea38881819c0e9f..e1e64f5c235802cfd013f946be6c16867fcd5ef5 100644 (file)
--- a/parse.y
+++ b/parse.y
@@ -295,6 +295,9 @@ int parser_state;
 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;
@@ -2143,7 +2146,8 @@ read_a_line (int remove_quoted_newline)
       /* 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)
@@ -2155,7 +2159,13 @@ read_a_line (int remove_quoted_newline)
          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';
        }
 
@@ -2177,10 +2187,12 @@ read_a_line (int remove_quoted_newline)
       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)
@@ -2200,7 +2212,11 @@ read_a_line (int remove_quoted_newline)
            }
          else
            {
-             yy_ungetc (peekc);
+             if (heredoc_string)
+               shell_ungetc (peekc);
+             else
+               yy_ungetc (peekc);
+
              pass_next = 1;
              line_buffer[indx++] = c;          /* Preserve the backslash. */
            }
@@ -2691,12 +2707,13 @@ next_alias_char:
      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' &&
@@ -3027,6 +3044,7 @@ gather_here_documents (void)
   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--;
index 752dd7d73fc2455c888848ad1e3eb3b46643ce1b..14cd41493e4c3af452c94bb17af518cad48f1404 100644 (file)
--- a/parser.h
+++ b/parser.h
@@ -103,6 +103,7 @@ extern int shell_eof_token;
 extern int current_token;
 extern int parser_state;
 extern int need_here_doc;
+extern int heredoc_string;
 
 extern int ignoreeof;
 extern int eof_encountered;
index 4c968346d17b4f2db53e8b3585ea4a917f3427ed..4aecfc354930db07e809961ae4d63937d9026fce 100644 (file)
Binary files a/po/pt_BR.gmo and b/po/pt_BR.gmo differ
index eaae6b58db5aeee813d43d497681ad2a186bc133..0c5b20e7e0815c8685a821cf888e7032d80c9319 100644 (file)
@@ -9,7 +9,7 @@ msgstr ""
 "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"
@@ -17,7 +17,7 @@ msgstr ""
 "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
index d5a4a7d7537564aa2919c17369bdb8e8ee3d6102..a504930616134dd6cea7c9ff038ff54b0e6038ab 100644 (file)
@@ -153,8 +153,14 @@ HERE
         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
 ''
index 2f94d1d721550502db0437bbc1e87d5a787fdcce..d6431b8a7119163ea0b0899a49f17e258a2fbdfe 100644 (file)
@@ -168,6 +168,9 @@ ${THIS_SH} ./heredoc8.sub
 # 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"
 )
diff --git a/tests/heredoc10.sub b/tests/heredoc10.sub
new file mode 100644 (file)
index 0000000..aa310e1
--- /dev/null
@@ -0,0 +1,45 @@
+#   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
index c766898cb999b0b12db2415edaf5e57ba9c897f2..608b647de55dcdc510c70b150b3a5a15aa0867ce 100644 (file)
@@ -38,6 +38,9 @@ abcde
 30
 40
 50
+declare -x var="60"
+outside
+assignment
 |0|10|
 10
 |0|10|
@@ -159,6 +162,8 @@ inside func: var=two
 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
index 8def153ad6f9c05aca197108dadb69b248df6c2b..b74de20c1dc4b9d446fa6db6e95d22c6b4d0ec67 100644 (file)
@@ -39,3 +39,26 @@ var=40 func
 
 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
index 92b3692f507a2333475178bb29fe84cf215346a3..441a02f03cc8d36bddf99a1994daae17564b49de 100644 (file)
@@ -134,6 +134,19 @@ echo -n 'outside 3.0: ' ; echo "var=${var-<unset>}"
 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