Imported from ../bash-2.05.tar.gz.
This commit is contained in:
parent
bb70624e96
commit
28ef6c316f
251 changed files with 22319 additions and 12413 deletions
315
parse.y
315
parse.y
|
@ -24,6 +24,8 @@
|
|||
#include "bashtypes.h"
|
||||
#include "bashansi.h"
|
||||
|
||||
#include "filecntl.h"
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
@ -77,9 +79,6 @@
|
|||
#define YYDEBUG 0
|
||||
|
||||
#if defined (EXTENDED_GLOB)
|
||||
#define PATTERN_CHAR(c) \
|
||||
((c) == '@' || (c) == '*' || (c) == '+' || (c) == '?' || (c) == '!')
|
||||
|
||||
extern int extended_glob;
|
||||
#endif
|
||||
|
||||
|
@ -127,6 +126,10 @@ static void reset_readline_prompt ();
|
|||
#endif
|
||||
static void print_prompt ();
|
||||
|
||||
#if defined (HISTORY)
|
||||
char *history_delimiting_chars ();
|
||||
#endif
|
||||
|
||||
extern int yyerror ();
|
||||
|
||||
/* Default prompt strings */
|
||||
|
@ -220,7 +223,7 @@ static REDIRECTEE redir;
|
|||
%type <command> arith_command
|
||||
%type <command> cond_command
|
||||
%type <command> arith_for_command
|
||||
%type <command> function_def if_command elif_clause subshell
|
||||
%type <command> function_def function_body if_command elif_clause subshell
|
||||
%type <redirect> redirection redirection_list
|
||||
%type <element> simple_command_element
|
||||
%type <word_list> word_list pattern
|
||||
|
@ -462,25 +465,6 @@ command: simple_command
|
|||
COMMAND *tc;
|
||||
|
||||
tc = $1;
|
||||
/* According to Posix.2 3.9.5, redirections
|
||||
specified after the body of a function should
|
||||
be attached to the function and performed when
|
||||
the function is executed, not as part of the
|
||||
function definition command. */
|
||||
/* XXX - I don't think it matters, but we might
|
||||
want to change this in the future to avoid
|
||||
problems differentiating between a function
|
||||
definition with a redirection and a function
|
||||
definition containing a single command with a
|
||||
redirection. The two are semantically equivalent,
|
||||
though -- the only difference is in how the
|
||||
command printing code displays the redirections. */
|
||||
if (tc->type == cm_function_def)
|
||||
{
|
||||
tc = tc->value.Function_def->command;
|
||||
if (tc->type == cm_group)
|
||||
tc = tc->value.Group->command;
|
||||
}
|
||||
if (tc->redirects)
|
||||
{
|
||||
register REDIRECT *t;
|
||||
|
@ -492,6 +476,8 @@ command: simple_command
|
|||
tc->redirects = $2;
|
||||
$$ = $1;
|
||||
}
|
||||
| function_def
|
||||
{ $$ = $1; }
|
||||
;
|
||||
|
||||
shell_command: for_command
|
||||
|
@ -516,8 +502,6 @@ shell_command: for_command
|
|||
{ $$ = $1; }
|
||||
| arith_for_command
|
||||
{ $$ = $1; }
|
||||
| function_def
|
||||
{ $$ = $1; }
|
||||
;
|
||||
|
||||
for_command: FOR WORD newline_list DO compound_list DONE
|
||||
|
@ -538,7 +522,12 @@ arith_for_command: FOR ARITH_FOR_EXPRS list_terminator newline_list DO compound_
|
|||
{ $$ = make_arith_for_command ($2, $6, arith_for_lineno); }
|
||||
| FOR ARITH_FOR_EXPRS list_terminator newline_list '{' compound_list '}'
|
||||
{ $$ = make_arith_for_command ($2, $6, arith_for_lineno); }
|
||||
| FOR ARITH_FOR_EXPRS DO compound_list DONE
|
||||
{ $$ = make_arith_for_command ($2, $4, arith_for_lineno); }
|
||||
| FOR ARITH_FOR_EXPRS '{' compound_list '}'
|
||||
{ $$ = make_arith_for_command ($2, $4, arith_for_lineno); }
|
||||
;
|
||||
|
||||
select_command: SELECT WORD newline_list DO list DONE
|
||||
{
|
||||
$$ = make_select_command ($2, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), $5);
|
||||
|
@ -573,17 +562,50 @@ case_command: CASE WORD newline_list IN newline_list ESAC
|
|||
{ $$ = make_case_command ($2, $5); }
|
||||
;
|
||||
|
||||
function_def: WORD '(' ')' newline_list group_command
|
||||
function_def: WORD '(' ')' newline_list function_body
|
||||
{ $$ = make_function_def ($1, $5, function_dstart, function_bstart); }
|
||||
|
||||
|
||||
| FUNCTION WORD '(' ')' newline_list group_command
|
||||
| FUNCTION WORD '(' ')' newline_list function_body
|
||||
{ $$ = make_function_def ($2, $6, function_dstart, function_bstart); }
|
||||
|
||||
| FUNCTION WORD newline_list group_command
|
||||
| FUNCTION WORD newline_list function_body
|
||||
{ $$ = make_function_def ($2, $4, function_dstart, function_bstart); }
|
||||
;
|
||||
|
||||
|
||||
function_body: shell_command
|
||||
{ $$ = $1; }
|
||||
| shell_command redirection_list
|
||||
{
|
||||
COMMAND *tc;
|
||||
|
||||
tc = $1;
|
||||
/* According to Posix.2 3.9.5, redirections
|
||||
specified after the body of a function should
|
||||
be attached to the function and performed when
|
||||
the function is executed, not as part of the
|
||||
function definition command. */
|
||||
/* XXX - I don't think it matters, but we might
|
||||
want to change this in the future to avoid
|
||||
problems differentiating between a function
|
||||
definition with a redirection and a function
|
||||
definition containing a single command with a
|
||||
redirection. The two are semantically equivalent,
|
||||
though -- the only difference is in how the
|
||||
command printing code displays the redirections. */
|
||||
if (tc->redirects)
|
||||
{
|
||||
register REDIRECT *t;
|
||||
for (t = tc->redirects; t->next; t = t->next)
|
||||
;
|
||||
t->next = $2;
|
||||
}
|
||||
else
|
||||
tc->redirects = $2;
|
||||
$$ = $1;
|
||||
}
|
||||
;
|
||||
|
||||
subshell: '(' compound_list ')'
|
||||
{
|
||||
$$ = make_subshell_command ($2);
|
||||
|
@ -600,7 +622,7 @@ if_command: IF compound_list THEN compound_list FI
|
|||
;
|
||||
|
||||
|
||||
group_command: '{' list '}'
|
||||
group_command: '{' compound_list '}'
|
||||
{ $$ = make_group_command ($2); }
|
||||
;
|
||||
|
||||
|
@ -809,15 +831,6 @@ timespec: TIME
|
|||
#define TOKEN_DEFAULT_INITIAL_SIZE 496
|
||||
#define TOKEN_DEFAULT_GROW_SIZE 512
|
||||
|
||||
/* Shell meta-characters that, when unquoted, separate words. */
|
||||
#define shellmeta(c) (strchr (shell_meta_chars, (c)) != 0)
|
||||
#define shellbreak(c) (strchr (shell_break_chars, (c)) != 0)
|
||||
#define shellquote(c) ((c) == '"' || (c) == '`' || (c) == '\'')
|
||||
#define shellexp(c) ((c) == '$' || (c) == '<' || (c) == '>')
|
||||
|
||||
char *shell_meta_chars = "()<>;&|";
|
||||
char *shell_break_chars = "()<>;&| \t\n";
|
||||
|
||||
/* The token currently being read. */
|
||||
static int current_token;
|
||||
|
||||
|
@ -966,7 +979,7 @@ yy_readline_get ()
|
|||
|
||||
#if defined (JOB_CONTROL)
|
||||
if (job_control)
|
||||
give_terminal_to (shell_pgrp);
|
||||
give_terminal_to (shell_pgrp, 0);
|
||||
#endif /* JOB_CONTROL */
|
||||
|
||||
if (signal_is_ignored (SIGINT) == 0)
|
||||
|
@ -1196,18 +1209,20 @@ pop_stream ()
|
|||
save stack, update the buffered fd to the new file descriptor and
|
||||
re-establish the buffer <-> bash_input fd correspondence. */
|
||||
if (bash_input.type == st_bstream && bash_input.location.buffered_fd >= 0)
|
||||
{
|
||||
if (bash_input_fd_changed)
|
||||
{
|
||||
if (bash_input_fd_changed)
|
||||
{
|
||||
bash_input_fd_changed = 0;
|
||||
if (default_buffered_input >= 0)
|
||||
{
|
||||
bash_input.location.buffered_fd = default_buffered_input;
|
||||
saver->bstream->b_fd = default_buffered_input;
|
||||
SET_CLOSE_ON_EXEC (default_buffered_input);
|
||||
}
|
||||
}
|
||||
/* XXX could free buffered stream returned as result here. */
|
||||
set_buffered_stream (bash_input.location.buffered_fd, saver->bstream);
|
||||
}
|
||||
}
|
||||
#endif /* BUFFERED_INPUT */
|
||||
|
||||
line_number = saver->line;
|
||||
|
@ -1412,8 +1427,14 @@ read_a_line (remove_quoted_newline)
|
|||
/* Allow immediate exit if interrupted during input. */
|
||||
QUIT;
|
||||
|
||||
/* Ignore null bytes in input. */
|
||||
if (c == 0)
|
||||
continue;
|
||||
{
|
||||
#if 0
|
||||
internal_warning ("read_a_line: ignored null byte in input");
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If there is no more input, then we return NULL. */
|
||||
if (c == EOF)
|
||||
|
@ -1435,10 +1456,10 @@ read_a_line (remove_quoted_newline)
|
|||
need to treat the backslash specially only if a backslash
|
||||
quoting a backslash-newline pair appears in the line. */
|
||||
if (pass_next)
|
||||
{
|
||||
{
|
||||
line_buffer[indx++] = c;
|
||||
pass_next = 0;
|
||||
}
|
||||
}
|
||||
else if (c == '\\' && remove_quoted_newline)
|
||||
{
|
||||
peekc = yy_getc ();
|
||||
|
@ -1516,8 +1537,8 @@ STRING_INT_ALIST word_token_alist[] = {
|
|||
};
|
||||
|
||||
/* XXX - we should also have an alist with strings for other tokens, so we
|
||||
can give more descriptive error messages. Look at y.tab.h for the
|
||||
other tokens. */
|
||||
can give more descriptive error messages. Look at y.tab.h for the
|
||||
other tokens. */
|
||||
|
||||
/* These are used by read_token_word, but appear up here so that shell_getc
|
||||
can use them to decide when to add otherwise blank lines to the history. */
|
||||
|
@ -1553,6 +1574,11 @@ static struct dstack temp_dstack = { (char *)NULL, 0, 0 };
|
|||
read the next line. This is called by read_token when the shell is
|
||||
processing normal command input. */
|
||||
|
||||
/* This implements one-character lookahead/lookbehind across physical input
|
||||
lines, to avoid something being lost because it's pushed back with
|
||||
shell_ungetc when we're at the start of a line. */
|
||||
static int eol_ungetc_lookahead = 0;
|
||||
|
||||
static int
|
||||
shell_getc (remove_quoted_newline)
|
||||
int remove_quoted_newline;
|
||||
|
@ -1563,6 +1589,13 @@ shell_getc (remove_quoted_newline)
|
|||
|
||||
QUIT;
|
||||
|
||||
if (eol_ungetc_lookahead)
|
||||
{
|
||||
c = eol_ungetc_lookahead;
|
||||
eol_ungetc_lookahead = 0;
|
||||
return (c);
|
||||
}
|
||||
|
||||
#if defined (ALIAS) || defined (DPAREN_ARITHMETIC)
|
||||
/* If shell_input_line[shell_input_line_index] == 0, but there is
|
||||
something on the pushed list of strings, then we don't want to go
|
||||
|
@ -1604,11 +1637,21 @@ shell_getc (remove_quoted_newline)
|
|||
if (bash_input.type == st_stream)
|
||||
clearerr (stdin);
|
||||
|
||||
while (c = yy_getc ())
|
||||
while (1)
|
||||
{
|
||||
c = yy_getc ();
|
||||
|
||||
/* Allow immediate exit if interrupted during input. */
|
||||
QUIT;
|
||||
|
||||
if (c == '\0')
|
||||
{
|
||||
#if 0
|
||||
internal_warning ("shell_getc: ignored null byte in input");
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
RESIZE_MALLOCED_BUFFER (shell_input_line, i, 2, shell_input_line_size, 256);
|
||||
|
||||
if (c == EOF)
|
||||
|
@ -1632,6 +1675,7 @@ shell_getc (remove_quoted_newline)
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
shell_input_line_index = 0;
|
||||
shell_input_line_len = i; /* == strlen (shell_input_line) */
|
||||
|
||||
|
@ -1663,20 +1707,29 @@ shell_getc (remove_quoted_newline)
|
|||
current_command_line_count--;
|
||||
|
||||
/* We have to force the xrealloc below because we don't know
|
||||
the true allocated size of shell_input_line anymore. */
|
||||
the true allocated size of shell_input_line anymore. */
|
||||
shell_input_line_size = shell_input_line_len;
|
||||
}
|
||||
}
|
||||
/* XXX - this is grotesque */
|
||||
/* Try to do something intelligent with blank lines encountered while
|
||||
entering multi-line commands. XXX - this is grotesque */
|
||||
else if (remember_on_history && shell_input_line &&
|
||||
shell_input_line[0] == '\0' &&
|
||||
current_command_line_count > 1 && current_delimiter (dstack))
|
||||
current_command_line_count > 1)
|
||||
{
|
||||
/* We know shell_input_line[0] == 0 and we're reading some sort of
|
||||
quoted string. This means we've got a line consisting of only
|
||||
a newline in a quoted string. We want to make sure this line
|
||||
gets added to the history. */
|
||||
maybe_add_history (shell_input_line);
|
||||
if (current_delimiter (dstack))
|
||||
/* We know shell_input_line[0] == 0 and we're reading some sort of
|
||||
quoted string. This means we've got a line consisting of only
|
||||
a newline in a quoted string. We want to make sure this line
|
||||
gets added to the history. */
|
||||
maybe_add_history (shell_input_line);
|
||||
else
|
||||
{
|
||||
char *hdcs;
|
||||
hdcs = history_delimiting_chars ();
|
||||
if (hdcs && hdcs[0] == ';')
|
||||
maybe_add_history (shell_input_line);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* HISTORY */
|
||||
|
@ -1732,18 +1785,18 @@ shell_getc (remove_quoted_newline)
|
|||
if (!c && (pushed_string_list != (STRING_SAVER *)NULL))
|
||||
{
|
||||
if (mustpop)
|
||||
{
|
||||
pop_string ();
|
||||
c = shell_input_line[shell_input_line_index];
|
||||
{
|
||||
pop_string ();
|
||||
c = shell_input_line[shell_input_line_index];
|
||||
if (c)
|
||||
shell_input_line_index++;
|
||||
mustpop--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mustpop++;
|
||||
c = ' ';
|
||||
}
|
||||
{
|
||||
mustpop++;
|
||||
c = ' ';
|
||||
}
|
||||
}
|
||||
#endif /* ALIAS || DPAREN_ARITHMETIC */
|
||||
|
||||
|
@ -1760,6 +1813,8 @@ shell_ungetc (c)
|
|||
{
|
||||
if (shell_input_line && shell_input_line_index)
|
||||
shell_input_line[--shell_input_line_index] = c;
|
||||
else
|
||||
eol_ungetc_lookahead = c;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1974,8 +2029,8 @@ time_command_acceptable ()
|
|||
case DO:
|
||||
case THEN:
|
||||
case ELSE:
|
||||
case '{':
|
||||
case '(':
|
||||
case '{': /* } */
|
||||
case '(': /* ) */
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
|
@ -1996,9 +2051,10 @@ time_command_acceptable ()
|
|||
to be set
|
||||
|
||||
`{' is recognized if the last token as WORD and the token
|
||||
before that was FUNCTION.
|
||||
before that was FUNCTION, or if we just parsed an arithmetic
|
||||
`for' command.
|
||||
|
||||
`}' is recognized if there is an unclosed `{' prsent.
|
||||
`}' is recognized if there is an unclosed `{' present.
|
||||
|
||||
`-p' is returned as TIMEOPT if the last read token was TIME.
|
||||
|
||||
|
@ -2066,6 +2122,16 @@ special_case_tokens (token)
|
|||
}
|
||||
}
|
||||
|
||||
/* We allow a `do' after a for ((...)) without an intervening
|
||||
list_terminator */
|
||||
if (last_read_token == ARITH_FOR_EXPRS && token[0] == 'd' && token[1] == 'o' && !token[2])
|
||||
return (DO);
|
||||
if (last_read_token == ARITH_FOR_EXPRS && token[0] == '{' && token[1] == '\0') /* } */
|
||||
{
|
||||
open_brace_count++;
|
||||
return ('{'); /* } */
|
||||
}
|
||||
|
||||
if (open_brace_count && reserved_word_acceptable (last_read_token) && token[0] == '}' && !token[1])
|
||||
{
|
||||
open_brace_count--; /* { */
|
||||
|
@ -2263,7 +2329,7 @@ read_token (command)
|
|||
if (cmdtyp == 1)
|
||||
{
|
||||
/* parse_arith_cmd adds quotes at the beginning and end
|
||||
of the string it returns; we need to take those out. */
|
||||
of the string it returns; we need to take those out. */
|
||||
len = strlen (wval);
|
||||
wv2 = xmalloc (len);
|
||||
strncpy (wv2, wval + 1, len - 2);
|
||||
|
@ -2342,7 +2408,7 @@ read_token (command)
|
|||
parser_state |= PST_SUBSHELL;
|
||||
/*(*/
|
||||
else if ((parser_state & PST_CASEPAT) && character == ')')
|
||||
parser_state &= ~PST_CASEPAT;
|
||||
parser_state &= ~PST_CASEPAT;
|
||||
/*(*/
|
||||
else if ((parser_state & PST_SUBSHELL) && character == ')')
|
||||
parser_state &= ~PST_SUBSHELL;
|
||||
|
@ -2386,8 +2452,8 @@ parse_matched_pair (qc, open, close, lenp, flags)
|
|||
int *lenp, flags;
|
||||
{
|
||||
int count, ch, was_dollar;
|
||||
int pass_next_character, nestlen, start_lineno;
|
||||
char *ret, *nestret;
|
||||
int pass_next_character, nestlen, ttranslen, start_lineno;
|
||||
char *ret, *nestret, *ttrans;
|
||||
int retind, retsize;
|
||||
|
||||
count = 1;
|
||||
|
@ -2440,7 +2506,7 @@ parse_matched_pair (qc, open, close, lenp, flags)
|
|||
#if 1
|
||||
/* handle nested ${...} specially. */
|
||||
else if (open != close && was_dollar && open == '{' && ch == open) /* } */
|
||||
count++;
|
||||
count++;
|
||||
#endif
|
||||
else if (((flags & P_FIRSTCLOSE) == 0) && ch == open) /* nested begin */
|
||||
count++;
|
||||
|
@ -2465,13 +2531,40 @@ parse_matched_pair (qc, open, close, lenp, flags)
|
|||
{
|
||||
/* '', ``, or "" inside $(...) or other grouping construct. */
|
||||
push_delimiter (dstack, ch);
|
||||
nestret = parse_matched_pair (ch, ch, ch, &nestlen, 0);
|
||||
if (was_dollar && ch == '\'') /* $'...' inside group */
|
||||
nestret = parse_matched_pair (ch, ch, ch, &nestlen, P_ALLOWESC);
|
||||
else
|
||||
nestret = parse_matched_pair (ch, ch, ch, &nestlen, 0);
|
||||
pop_delimiter (dstack);
|
||||
if (nestret == &matched_pair_error)
|
||||
{
|
||||
free (ret);
|
||||
return &matched_pair_error;
|
||||
}
|
||||
if (was_dollar && ch == '\'')
|
||||
{
|
||||
/* Translate $'...' here. */
|
||||
ttrans = ansiexpand (nestret, 0, nestlen - 1, &ttranslen);
|
||||
free (nestret);
|
||||
nestret = sh_single_quote (ttrans);
|
||||
free (ttrans);
|
||||
nestlen = strlen (nestret);
|
||||
retind -= 2; /* back up before the $' */
|
||||
}
|
||||
else if (was_dollar && ch == '"')
|
||||
{
|
||||
/* Locale expand $"..." here. */
|
||||
ttrans = localeexpand (nestret, 0, nestlen - 1, start_lineno, &ttranslen);
|
||||
free (nestret);
|
||||
nestret = xmalloc (ttranslen + 3);
|
||||
nestret[0] = '"';
|
||||
strcpy (nestret + 1, ttrans);
|
||||
nestret[ttranslen + 1] = '"';
|
||||
nestret[ttranslen += 2] = '\0';
|
||||
free (ttrans);
|
||||
nestlen = ttranslen;
|
||||
retind -= 2; /* back up before the $" */
|
||||
}
|
||||
if (nestlen)
|
||||
{
|
||||
RESIZE_MALLOCED_BUFFER (ret, retind, nestlen, retsize, 64);
|
||||
|
@ -2696,14 +2789,16 @@ cond_term ()
|
|||
/* binop */
|
||||
tok = read_token (READ);
|
||||
if (tok == WORD && test_binop (yylval.word->word))
|
||||
op = yylval.word;
|
||||
op = yylval.word;
|
||||
else if (tok == '<' || tok == '>')
|
||||
op = make_word_from_token (tok);
|
||||
else if (tok == COND_END || tok == AND_AND || tok == OR_OR)
|
||||
op = make_word_from_token (tok); /* ( */
|
||||
/* There should be a check before blindly accepting the `)' that we have
|
||||
seen the opening `('. */
|
||||
else if (tok == COND_END || tok == AND_AND || tok == OR_OR || tok == ')')
|
||||
{
|
||||
/* Special case. [[ x ]] is equivalent to [[ -n x ]], just like
|
||||
the test command. Similarly for [[ x && expr ]] or
|
||||
[[ x || expr ]] */
|
||||
[[ x || expr ]] or [[ (x) ]]. */
|
||||
op = make_word ("-n");
|
||||
term = make_cond_node (COND_UNARY, op, tleft, (COND_COM *)NULL);
|
||||
cond_token = tok;
|
||||
|
@ -2789,7 +2884,7 @@ read_token_word (character)
|
|||
token = xrealloc (token, token_buffer_size = TOKEN_DEFAULT_INITIAL_SIZE);
|
||||
|
||||
token_index = 0;
|
||||
all_digits = digit (character);
|
||||
all_digits = isdigit (character);
|
||||
dollar_present = quoted = pass_next_character = 0;
|
||||
|
||||
for (;;)
|
||||
|
@ -2824,7 +2919,7 @@ read_token_word (character)
|
|||
|
||||
/* If the next character is to be quoted, note it now. */
|
||||
if (cd == 0 || cd == '`' ||
|
||||
(cd == '"' && member (peek_char, slashify_in_quotes)))
|
||||
(cd == '"' && (sh_syntaxtab[peek_char] & CBSDQUOTE)))
|
||||
pass_next_character++;
|
||||
|
||||
quoted = 1;
|
||||
|
@ -2854,7 +2949,7 @@ read_token_word (character)
|
|||
|
||||
#ifdef EXTENDED_GLOB
|
||||
/* Parse a ksh-style extended pattern matching specification. */
|
||||
if (extended_glob && PATTERN_CHAR(character))
|
||||
if (extended_glob && PATTERN_CHAR (character))
|
||||
{
|
||||
peek_char = shell_getc (1);
|
||||
if (peek_char == '(') /* ) */
|
||||
|
@ -2882,11 +2977,7 @@ read_token_word (character)
|
|||
|
||||
/* If the delimiter character is not single quote, parse some of
|
||||
the shell expansions that must be read as a single word. */
|
||||
#if defined (PROCESS_SUBSTITUTION)
|
||||
if (character == '$' || character == '<' || character == '>')
|
||||
#else
|
||||
if (character == '$')
|
||||
#endif /* !PROCESS_SUBSTITUTION */
|
||||
if (shellexp (character))
|
||||
{
|
||||
peek_char = shell_getc (1);
|
||||
/* $(...), <(...), >(...), $((...)), ${...}, and $[...] constructs */
|
||||
|
@ -2894,7 +2985,7 @@ read_token_word (character)
|
|||
((peek_char == '{' || peek_char == '[') && character == '$')) /* ) ] } */
|
||||
{
|
||||
if (peek_char == '{') /* } */
|
||||
ttok = parse_matched_pair (cd, '{', '}', &ttoklen, P_FIRSTCLOSE);
|
||||
ttok = parse_matched_pair (cd, '{', '}', &ttoklen, P_FIRSTCLOSE);
|
||||
else if (peek_char == '(') /* ) */
|
||||
{
|
||||
/* XXX - push and pop the `(' as a delimiter for use by
|
||||
|
@ -2942,7 +3033,7 @@ read_token_word (character)
|
|||
/* Insert the single quotes and correctly quote any
|
||||
embedded single quotes (allowed because P_ALLOWESC was
|
||||
passed to parse_matched_pair). */
|
||||
ttok = single_quote (ttrans);
|
||||
ttok = sh_single_quote (ttrans);
|
||||
free (ttrans);
|
||||
ttrans = ttok;
|
||||
ttranslen = strlen (ttrans);
|
||||
|
@ -3035,7 +3126,7 @@ read_token_word (character)
|
|||
|
||||
got_character:
|
||||
|
||||
all_digits &= digit (character);
|
||||
all_digits &= isdigit (character);
|
||||
dollar_present |= character == '$';
|
||||
|
||||
if (character == CTLESC || character == CTLNUL)
|
||||
|
@ -3181,7 +3272,7 @@ mk_msgstr (string, foundnlp)
|
|||
if (*s == '"' || *s == '\\')
|
||||
len++;
|
||||
else if (*s == '\n')
|
||||
len += 5;
|
||||
len += 5;
|
||||
}
|
||||
|
||||
r = result = xmalloc (len + 3);
|
||||
|
@ -3380,9 +3471,9 @@ history_delimiting_chars ()
|
|||
/* This does not work for subshells inside case statement
|
||||
command lists. It's a suboptimal solution. */
|
||||
else if (parser_state & PST_CASESTMT) /* case statement pattern */
|
||||
return " ";
|
||||
return " ";
|
||||
else
|
||||
return "; "; /* (...) subshell */
|
||||
return "; "; /* (...) subshell */
|
||||
}
|
||||
else if (token_before_that == WORD && two_tokens_ago == FUNCTION)
|
||||
return " "; /* function def using `function name' without `()' */
|
||||
|
@ -3392,7 +3483,7 @@ history_delimiting_chars ()
|
|||
/* Tricky. `for i\nin ...' should not have a semicolon, but
|
||||
`for i\ndo ...' should. We do what we can. */
|
||||
for (i = shell_input_line_index; whitespace(shell_input_line[i]); i++)
|
||||
;
|
||||
;
|
||||
if (shell_input_line[i] && shell_input_line[i] == 'i' && shell_input_line[i+1] == 'n')
|
||||
return " ";
|
||||
return ";";
|
||||
|
@ -3560,7 +3651,6 @@ decode_prompt_string (string)
|
|||
|
||||
if (n == CTLESC || n == CTLNUL)
|
||||
{
|
||||
string += 3;
|
||||
temp[0] = CTLESC;
|
||||
temp[1] = n;
|
||||
temp[2] = '\0';
|
||||
|
@ -3572,11 +3662,13 @@ decode_prompt_string (string)
|
|||
}
|
||||
else
|
||||
{
|
||||
string += 3;
|
||||
temp[0] = n;
|
||||
temp[1] = '\0';
|
||||
}
|
||||
|
||||
for (c = 0; n != -1 && c < 3 && ISOCTAL (*string); c++)
|
||||
string++;
|
||||
|
||||
c = 0;
|
||||
goto add_string;
|
||||
|
||||
|
@ -3655,7 +3747,7 @@ decode_prompt_string (string)
|
|||
{
|
||||
if (getcwd (t_string, sizeof(t_string)) == 0)
|
||||
{
|
||||
t_string[0] = '.';
|
||||
t_string[0] = '.';
|
||||
tlen = 1;
|
||||
}
|
||||
else
|
||||
|
@ -3668,12 +3760,19 @@ decode_prompt_string (string)
|
|||
}
|
||||
t_string[tlen] = '\0';
|
||||
|
||||
#define ROOT_PATH(x) ((x)[0] == '/' && (x)[1] == 0)
|
||||
#define DOUBLE_SLASH_ROOT(x) ((x)[0] == '/' && (x)[1] == '/' && (x)[2] == 0)
|
||||
if (c == 'W')
|
||||
{
|
||||
t = strrchr (t_string, '/');
|
||||
if (t && t != t_string)
|
||||
strcpy (t_string, t + 1);
|
||||
if (ROOT_PATH (t_string) == 0 && DOUBLE_SLASH_ROOT (t_string) == 0)
|
||||
{
|
||||
t = strrchr (t_string, '/');
|
||||
if (t)
|
||||
strcpy (t_string, t + 1);
|
||||
}
|
||||
}
|
||||
#undef ROOT_PATH
|
||||
#undef DOUBLE_SLASH_ROOT
|
||||
else
|
||||
/* polite_directory_format is guaranteed to return a string
|
||||
no longer than PATH_MAX - 1 characters. */
|
||||
|
@ -3682,14 +3781,10 @@ decode_prompt_string (string)
|
|||
/* If we're going to be expanding the prompt string later,
|
||||
quote the directory name. */
|
||||
if (promptvars || posixly_correct)
|
||||
#if 0
|
||||
temp = backslash_quote (t_string);
|
||||
#else
|
||||
/* Make sure that expand_prompt_string is called with a
|
||||
second argument of Q_DOUBLE_QUOTE if we use this
|
||||
function here. */
|
||||
temp = backslash_quote_for_double_quotes (t_string);
|
||||
#endif
|
||||
temp = sh_backslash_quote_for_double_quotes (t_string);
|
||||
else
|
||||
temp = savestring (t_string);
|
||||
|
||||
|
@ -3804,11 +3899,7 @@ decode_prompt_string (string)
|
|||
the prompt string. */
|
||||
if (promptvars || posixly_correct)
|
||||
{
|
||||
#if 0
|
||||
list = expand_string_unsplit (result, Q_DOUBLE_QUOTES);
|
||||
#else
|
||||
list = expand_prompt_string (result, Q_DOUBLE_QUOTES);
|
||||
#endif
|
||||
free (result);
|
||||
result = string_list (list);
|
||||
dispose_words (list);
|
||||
|
@ -3998,6 +4089,7 @@ parse_string_to_word_list (s, whom)
|
|||
{
|
||||
WORD_LIST *wl;
|
||||
int tok, orig_line_number, orig_input_terminator;
|
||||
int orig_line_count;
|
||||
#if defined (HISTORY)
|
||||
int old_remember_on_history, old_history_expansion_inhibited;
|
||||
#endif
|
||||
|
@ -4011,10 +4103,12 @@ parse_string_to_word_list (s, whom)
|
|||
#endif
|
||||
|
||||
orig_line_number = line_number;
|
||||
orig_line_count = current_command_line_count;
|
||||
orig_input_terminator = shell_input_line_terminator;
|
||||
|
||||
push_stream (1);
|
||||
last_read_token = '\n';
|
||||
current_command_line_count = 0;
|
||||
|
||||
with_input_from_string (s, whom);
|
||||
wl = (WORD_LIST *)NULL;
|
||||
|
@ -4022,6 +4116,8 @@ parse_string_to_word_list (s, whom)
|
|||
{
|
||||
if (tok == '\n' && *bash_input.location.string == '\0')
|
||||
break;
|
||||
if (tok == '\n') /* Allow newlines in compound assignments */
|
||||
continue;
|
||||
if (tok != WORD && tok != ASSIGNMENT_WORD)
|
||||
{
|
||||
line_number = orig_line_number + line_number - 1;
|
||||
|
@ -4044,6 +4140,7 @@ parse_string_to_word_list (s, whom)
|
|||
# endif /* BANG_HISTORY */
|
||||
#endif /* HISTORY */
|
||||
|
||||
current_command_line_count = orig_line_count;
|
||||
shell_input_line_terminator = orig_input_terminator;
|
||||
|
||||
if (wl == &parse_string_error)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue