mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-06-26 15:23:09 +02:00
changes to text representation of parsed command substitution; small changes to tests
This commit is contained in:
@@ -321,7 +321,10 @@ b. There is a new internal timer framework used for read builtin timeouts.
|
||||
|
||||
c. Rewrote the command substitution parsing code to call the parser recursively
|
||||
and rebuild the command string from the parsed command. This allows better
|
||||
syntax checking and catches errors much earlier.
|
||||
syntax checking and catches errors much earlier. Along with this, if
|
||||
command substitution parsing completes with here-documents remaining to be
|
||||
read, the shell prints a warning message and reads the here-document bodies
|
||||
from the current input stream.
|
||||
|
||||
d. The `ulimit' builtin now treats an operand remaining after all of the options
|
||||
and arguments are parsed as an argument to the last command specified by
|
||||
|
||||
+4
-1
@@ -321,7 +321,10 @@ b. There is a new internal timer framework used for read builtin timeouts.
|
||||
|
||||
c. Rewrote the command substitution parsing code to call the parser recursively
|
||||
and rebuild the command string from the parsed command. This allows better
|
||||
syntax checking and catches errors much earlier.
|
||||
syntax checking and catches errors much earlier. Along with this, if
|
||||
command substitution parsing completes with here-documents remaining to be
|
||||
read, the shell prints a warning message and reads the here-document bodies
|
||||
from the current input stream.
|
||||
|
||||
d. The `ulimit' builtin now treats an operand remaining after all of the options
|
||||
and arguments are parsed as an argument to the last command specified by
|
||||
|
||||
@@ -3731,3 +3731,21 @@ subst.c
|
||||
indicating that we're doing this for completion, probably to
|
||||
determine whether or not to append something to the word. Fixes bug
|
||||
reported by Emanuele Torre <torreemanuele6@gmail.com>.
|
||||
|
||||
7/5
|
||||
---
|
||||
execute_cmd.c
|
||||
- execute_connection: treat a connector of '\n' the same as ';'
|
||||
|
||||
print_cmd.c
|
||||
- print_comsub: new function, sets flag noting we are printing a
|
||||
command substitution and calls make_command_string
|
||||
- make_command_string_internal: add '\n' to the ';' case; print command
|
||||
list with newline connector appropriately
|
||||
parse.y
|
||||
- parse_comsub: call print_comsub instead of make_command_string
|
||||
- list1 production (part of compound_list): if a list is separated by
|
||||
newlines, and the parser is parsing a command substitution, make
|
||||
the connection command with a '\n' connector. Makes the text
|
||||
output of parse_comsub closer to the original source text. From a
|
||||
report from Martijn Dekker <martijn@inlv.org>
|
||||
|
||||
@@ -10,7 +10,10 @@ b. There is a new internal timer framework used for read builtin timeouts.
|
||||
|
||||
c. Rewrote the command substitution parsing code to call the parser recursively
|
||||
and rebuild the command string from the parsed command. This allows better
|
||||
syntax checking and catches errors much earlier.
|
||||
syntax checking and catches errors much earlier. Along with this, if
|
||||
command substitution parsing completes with here-documents remaining to be
|
||||
read, the shell prints a warning message and reads the here-document bodies
|
||||
from the current input stream.
|
||||
|
||||
d. The `ulimit' builtin now treats an operand remaining after all of the options
|
||||
and arguments are parsed as an argument to the last command specified by
|
||||
|
||||
@@ -10,7 +10,10 @@ b. There is a new internal timer framework used for read builtin timeouts.
|
||||
|
||||
c. Rewrote the command substitution parsing code to call the parser recursively
|
||||
and rebuild the command string from the parsed command. This allows better
|
||||
syntax checking and catches errors much earlier.
|
||||
syntax checking and catches errors much earlier. Along with this, if
|
||||
command substitution parsing completes with here-documents remaining to be
|
||||
read, the shell prints a warning message and reads the here-document bodies
|
||||
from the current input stream.
|
||||
|
||||
d. The `ulimit' builtin now treats an operand remaining after all of the options
|
||||
and arguments are parsed as an argument to the last command specified by
|
||||
|
||||
@@ -2738,6 +2738,7 @@ execute_connection (command, asynchronous, pipe_in, pipe_out, fds_to_close)
|
||||
|
||||
/* Just call execute command on both sides. */
|
||||
case ';':
|
||||
case '\n': /* special case, happens in command substitutions */
|
||||
if (ignore_return)
|
||||
{
|
||||
if (command->value.Connection->first)
|
||||
|
||||
@@ -36,6 +36,7 @@ extern intmax_t evalexp PARAMS((char *, int, int *));
|
||||
#define FUNC_EXTERNAL 0x02
|
||||
|
||||
extern char *make_command_string PARAMS((COMMAND *));
|
||||
extern char *print_comsub PARAMS((COMMAND *));
|
||||
extern char *named_function_string PARAMS((char *, COMMAND *, int));
|
||||
|
||||
extern void print_command PARAMS((COMMAND *));
|
||||
|
||||
@@ -1154,7 +1154,12 @@ list1: list1 AND_AND newline_list list1
|
||||
| list1 ';' newline_list list1
|
||||
{ $$ = command_connect ($1, $4, ';'); }
|
||||
| list1 '\n' newline_list list1
|
||||
{ $$ = command_connect ($1, $4, ';'); }
|
||||
{
|
||||
if (parser_state & PST_CMDSUBST)
|
||||
$$ = command_connect ($1, $4, '\n');
|
||||
else
|
||||
$$ = command_connect ($1, $4, ';');
|
||||
}
|
||||
| pipeline_command
|
||||
{ $$ = $1; }
|
||||
;
|
||||
@@ -1188,7 +1193,7 @@ simple_list: simple_list1
|
||||
gather_here_documents ();
|
||||
if ((parser_state & PST_CMDSUBST) && current_token == shell_eof_token)
|
||||
{
|
||||
itrace("LEGACY: parser: command substitution simple_list1 -> simple_list");
|
||||
INTERNAL_DEBUG (("LEGACY: parser: command substitution simple_list1 -> simple_list"));
|
||||
global_command = $1;
|
||||
eof_encountered = 0;
|
||||
if (bash_input.type == st_string)
|
||||
@@ -1206,7 +1211,7 @@ itrace("LEGACY: parser: command substitution simple_list1 -> simple_list");
|
||||
gather_here_documents ();
|
||||
if ((parser_state & PST_CMDSUBST) && current_token == shell_eof_token)
|
||||
{
|
||||
itrace("LEGACY: parser: command substitution simple_list1 '&' -> simple_list");
|
||||
INTERNAL_DEBUG (("LEGACY: parser: command substitution simple_list1 '&' -> simple_list"));
|
||||
global_command = $1;
|
||||
eof_encountered = 0;
|
||||
if (bash_input.type == st_string)
|
||||
@@ -1221,7 +1226,7 @@ itrace("LEGACY: parser: command substitution simple_list1 '&' -> simple_list");
|
||||
gather_here_documents ();
|
||||
if ((parser_state & PST_CMDSUBST) && current_token == shell_eof_token)
|
||||
{
|
||||
itrace("LEGACY: parser: command substitution simple_list1 ';' -> simple_list");
|
||||
INTERNAL_DEBUG (("LEGACY: parser: command substitution simple_list1 ';' -> simple_list"));
|
||||
global_command = $1;
|
||||
eof_encountered = 0;
|
||||
if (bash_input.type == st_string)
|
||||
@@ -4095,8 +4100,8 @@ parse_comsub (qc, open, close, lenp, flags)
|
||||
|
||||
if (need_here_doc > 0)
|
||||
{
|
||||
internal_debug("command substitution: %d unterminated here-document%s", need_here_doc, (need_here_doc == 1) ? "" : "s");
|
||||
gather_here_documents ();
|
||||
internal_warning ("command substitution: %d unterminated here-document%s", need_here_doc, (need_here_doc == 1) ? "" : "s");
|
||||
gather_here_documents (); /* XXX check compatibility level? */
|
||||
}
|
||||
|
||||
parsed_command = global_command;
|
||||
@@ -4126,7 +4131,7 @@ INTERNAL_DEBUG(("current_token (%d) != shell_eof_token (%c)", current_token, she
|
||||
|
||||
restore_parser_state (&ps);
|
||||
|
||||
tcmd = make_command_string (parsed_command); /* returns static memory */
|
||||
tcmd = print_comsub (parsed_command); /* returns static memory */
|
||||
retlen = strlen (tcmd);
|
||||
if (tcmd[0] == '(') /* ) need a space to prevent arithmetic expansion */
|
||||
retlen++;
|
||||
|
||||
+46
-18
@@ -129,6 +129,7 @@ static int inside_function_def;
|
||||
static int skip_this_indent;
|
||||
static int was_heredoc;
|
||||
static int printing_connection;
|
||||
static int printing_comsub;
|
||||
static REDIRECT *deferred_heredocs;
|
||||
|
||||
/* The depth of the group commands that we are currently printing. This
|
||||
@@ -162,6 +163,21 @@ make_command_string (command)
|
||||
return (the_printed_command);
|
||||
}
|
||||
|
||||
/* Print a command substitution after parsing it in parse_comsub to turn it
|
||||
back into an external representation without turning newlines into `;'.
|
||||
Placeholder for other changes, if any are necessary. */
|
||||
char *
|
||||
print_comsub (command)
|
||||
COMMAND *command;
|
||||
{
|
||||
char *ret;
|
||||
|
||||
printing_comsub++;
|
||||
ret = make_command_string (command);
|
||||
printing_comsub--;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* The internal function. This is the real workhorse. */
|
||||
static void
|
||||
make_command_string_internal (command)
|
||||
@@ -278,25 +294,35 @@ make_command_string_internal (command)
|
||||
break;
|
||||
|
||||
case ';':
|
||||
if (deferred_heredocs == 0)
|
||||
{
|
||||
if (was_heredoc == 0)
|
||||
cprintf (";");
|
||||
else
|
||||
was_heredoc = 0;
|
||||
}
|
||||
else
|
||||
print_deferred_heredocs (inside_function_def ? "" : ";");
|
||||
case '\n': /* special case this */
|
||||
{
|
||||
char c = command->value.Connection->connector;
|
||||
|
||||
if (inside_function_def)
|
||||
cprintf ("\n");
|
||||
else
|
||||
{
|
||||
cprintf (" ");
|
||||
if (command->value.Connection->second)
|
||||
skip_this_indent++;
|
||||
}
|
||||
break;
|
||||
s[0] = printing_comsub ? c : ';';
|
||||
s[1] = '\0';
|
||||
|
||||
if (deferred_heredocs == 0)
|
||||
{
|
||||
if (was_heredoc == 0)
|
||||
cprintf (s); /* inside_function_def? */
|
||||
else
|
||||
was_heredoc = 0;
|
||||
}
|
||||
else
|
||||
/* print_deferred_heredocs special-cases `;' */
|
||||
print_deferred_heredocs (inside_function_def ? "" : ";");
|
||||
|
||||
if (inside_function_def)
|
||||
cprintf ("\n");
|
||||
else
|
||||
{
|
||||
if (c == ';')
|
||||
cprintf (" ");
|
||||
if (command->value.Connection->second)
|
||||
skip_this_indent++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
cprintf (_("print_command: bad connector `%d'"),
|
||||
@@ -1293,6 +1319,7 @@ reset_locals ()
|
||||
indentation = 0;
|
||||
printing_connection = 0;
|
||||
deferred_heredocs = 0;
|
||||
printing_comsub = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1364,6 +1391,7 @@ named_function_string (name, command, flags)
|
||||
old_amount = indentation_amount;
|
||||
command_string_index = was_heredoc = 0;
|
||||
deferred_heredocs = 0;
|
||||
printing_comsub = 0;
|
||||
|
||||
if (name && *name)
|
||||
{
|
||||
|
||||
+15
-8
@@ -53,16 +53,23 @@ unset before after
|
||||
# date +%s should be portable enough now
|
||||
# then try gawk, perl, python in that order
|
||||
now1=$(date +%s 2>/dev/null) D=date
|
||||
[ -z "$now1" ] && now1=$(gawk 'BEGIN { print systime(); }' 2>/dev/null) D=gawk
|
||||
[ -z "$now1" ] && now1=$(perl -e 'print time' 2>/dev/null) D=perl
|
||||
[ -z "$now1" ] && now1=$(python -c 'import time; ts = int(time.time()); print(ts)' 2>/dev/null) D=python
|
||||
[ -z "$now1" ] &&
|
||||
{
|
||||
now1=$(gawk 'BEGIN { print systime(); }' 2>/dev/null) D=gawk
|
||||
[ -z "$now1" ] && now1=$(perl -e 'print time' 2>/dev/null) D=perl
|
||||
[ -z "$now1" ] && now1=$(python -c 'import time; ts = int(time.time()); print(ts)' 2>/dev/null) D=python
|
||||
}
|
||||
now2=$EPOCHSECONDS
|
||||
|
||||
case $now1 in
|
||||
$now2) echo EPOCHSECONDS ok ;;
|
||||
'') echo "cannot get current time using date/gawk/perl/python" >&2 ;;
|
||||
*) echo "current time via $D and EPOCHSECONDS possible mismatch|$now1|$now2" >&2 ;;
|
||||
esac
|
||||
# use a window of +-1 second
|
||||
offset=1
|
||||
if [[ -z $now1 ]]; then
|
||||
echo "cannot get current time using date/gawk/perl/python" >&2
|
||||
elif (( $now1 - $offset <= $now2 && $now2 <= $now1 + $offset )); then
|
||||
echo EPOCHSECONDS ok
|
||||
else
|
||||
echo "current time via $D and EPOCHSECONDS possible mismatch|$now1|$now2|offset=$offset" >&2
|
||||
fi
|
||||
unset now1 now2 D
|
||||
|
||||
LC_ALL=C # force decimal point to `.'
|
||||
|
||||
+2
-1
@@ -120,11 +120,12 @@ argv[3] = <ve>
|
||||
5: ${x#$pat}
|
||||
6: ${y#$'not'}
|
||||
7: ${y#'not'}
|
||||
./heredoc7.sub: line 17: warning: command substitution: 1 unterminated here-document
|
||||
foo bar
|
||||
./heredoc7.sub: line 21: after: command not found
|
||||
./heredoc7.sub: line 29: warning: here-document at line 29 delimited by end-of-file (wanted `EOF')
|
||||
./heredoc7.sub: line 29: foobar: command not found
|
||||
./heredoc7.sub: line 29: EOF: command not found
|
||||
./heredoc7.sub: line 30: EOF: command not found
|
||||
grep: *.c: No such file or directory
|
||||
comsub here-string
|
||||
./heredoc.tests: line 156: warning: here-document at line 154 delimited by end-of-file (wanted `EOF')
|
||||
|
||||
Reference in New Issue
Block a user