X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=parse.y;h=8a2b081ac0ff8a7d394962c514e19ad63b30ea54;hb=f1be666c7d78939ad775078d290bec2758fa29a2;hp=363430e5b60a9c286004fc108c4a11c3a60c07ff;hpb=b80f6443b6b7b620c7272664c66ecb0b120a0998;p=platform%2Fupstream%2Fbash.git diff --git a/parse.y b/parse.y index 363430e..8a2b081 100644 --- a/parse.y +++ b/parse.y @@ -1,6 +1,6 @@ /* Yacc grammar for bash. */ -/* Copyright (C) 1989-2004 Free Software Foundation, Inc. +/* Copyright (C) 1989-2006 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne Again SHell. @@ -50,6 +50,7 @@ #include "parser.h" #include "mailcheck.h" #include "test.h" +#include "builtins.h" #include "builtins/common.h" #include "builtins/builtext.h" @@ -117,7 +118,6 @@ extern int current_command_number; extern int sourcelevel; extern int posixly_correct; extern int last_command_exit_value; -extern int interrupt_immediately; extern char *shell_name, *current_host_name; extern char *dist_version; extern int patch_level; @@ -205,10 +205,6 @@ static void reset_readline_prompt __P((void)); #endif static void print_prompt __P((void)); -#if defined (HISTORY) -char *history_delimiting_chars __P((void)); -#endif - #if defined (HANDLE_MULTIBYTE) static void set_line_mbstate __P((void)); static char *shell_input_line_property = NULL; @@ -961,22 +957,26 @@ pipeline_command: pipeline { $$ = $1; } | BANG pipeline { - $2->flags |= CMD_INVERT_RETURN; + if ($2) + $2->flags |= CMD_INVERT_RETURN; $$ = $2; } | timespec pipeline { - $2->flags |= $1; + if ($2) + $2->flags |= $1; $$ = $2; } | timespec BANG pipeline { - $3->flags |= $1|CMD_INVERT_RETURN; + if ($3) + $3->flags |= $1|CMD_INVERT_RETURN; $$ = $3; } | BANG timespec pipeline { - $3->flags |= $2|CMD_INVERT_RETURN; + if ($3) + $3->flags |= $2|CMD_INVERT_RETURN; $$ = $3; } | timespec list_terminator @@ -1028,6 +1028,8 @@ timespec: TIME #define PST_ALEXPAND 0x0800 /* OK to expand aliases - unused */ #define PST_CMDTOKEN 0x1000 /* command token OK - unused */ #define PST_COMPASSIGN 0x2000 /* parsing x=(...) compound assignment */ +#define PST_ASSIGNOK 0x4000 /* assignment statement ok in this context */ +#define PST_REGEXP 0x8000 /* parsing an ERE/BRE as a single word */ /* Initial size to allocate for tokens, and the amount to grow them by. */ @@ -1206,10 +1208,12 @@ yy_readline_get () old_sigint = (SigHandler *)set_signal_handler (SIGINT, sigint_sighandler); interrupt_immediately++; } + terminate_immediately = 1; current_readline_line = readline (current_readline_prompt ? current_readline_prompt : ""); + terminate_immediately = 0; if (signal_is_ignored (SIGINT) == 0 && old_sigint) { interrupt_immediately--; @@ -1339,8 +1343,19 @@ yy_stream_get () result = EOF; if (bash_input.location.file) - result = getc_with_restart (bash_input.location.file); - + { + if (interactive) + { + interrupt_immediately++; + terminate_immediately++; + } + result = getc_with_restart (bash_input.location.file); + if (interactive) + { + interrupt_immediately--; + terminate_immediately--; + } + } return (result); } @@ -1653,11 +1668,11 @@ read_a_line (remove_quoted_newline) pass_next = 0; while (1) { - c = yy_getc (); - /* Allow immediate exit if interrupted during input. */ QUIT; + c = yy_getc (); + /* Ignore null bytes in input. */ if (c == 0) { @@ -1858,10 +1873,15 @@ shell_getc (remove_quoted_newline) register int i; int c; unsigned char uc; - static int mustpop = 0; QUIT; + if (sigwinch_received) + { + sigwinch_received = 0; + get_new_window_size (0, (int *)0, (int *)0); + } + if (eol_ungetc_lookahead) { c = eol_ungetc_lookahead; @@ -2055,14 +2075,6 @@ shell_getc (remove_quoted_newline) if (uc) shell_input_line_index++; - if MBTEST(uc == '\\' && remove_quoted_newline && shell_input_line[shell_input_line_index] == '\n') - { - if (SHOULD_PROMPT ()) - prompt_again (); - line_number++; - goto restart_read; - } - #if defined (ALIAS) || defined (DPAREN_ARITHMETIC) /* If UC is NULL, we have reached the end of the current input string. If pushed_string_list is non-empty, it's time to pop to the previous string @@ -2078,6 +2090,14 @@ shell_getc (remove_quoted_newline) } #endif /* ALIAS || DPAREN_ARITHMETIC */ + if MBTEST(uc == '\\' && remove_quoted_newline && shell_input_line[shell_input_line_index] == '\n') + { + if (SHOULD_PROMPT ()) + prompt_again (); + line_number++; + goto restart_read; + } + if (!uc && shell_input_line_terminator == EOF) return ((shell_input_line_index != 0) ? '\n' : EOF); @@ -2125,8 +2145,8 @@ discard_until (character) } void -execute_prompt_command (command) - char *command; +execute_variable_command (command, vname) + char *command, *vname; { char *last_lastarg; sh_parser_state_t ps; @@ -2136,10 +2156,10 @@ execute_prompt_command (command) if (last_lastarg) last_lastarg = savestring (last_lastarg); - parse_and_execute (savestring (command), "PROMPT_COMMAND", SEVAL_NONINT|SEVAL_NOHIST); + parse_and_execute (savestring (command), vname, SEVAL_NONINT|SEVAL_NOHIST); restore_parser_state (&ps); - bind_variable ("_", last_lastarg); + bind_variable ("_", last_lastarg, 0); FREE (last_lastarg); if (token_to_read == '\n') /* reset_parser was called */ @@ -2539,7 +2559,7 @@ read_token (command) #endif /* ALIAS */ /* Read a single word from input. Start by skipping blanks. */ - while ((character = shell_getc (1)) != EOF && whitespace (character)) + while ((character = shell_getc (1)) != EOF && shellblank (character)) ; if (character == EOF) @@ -2567,9 +2587,14 @@ read_token (command) parser_state &= ~PST_ALEXPNEXT; #endif /* ALIAS */ + parser_state &= ~PST_ASSIGNOK; + return (character); } + if (parser_state & PST_REGEXP) + goto tokword; + /* Shell meta-characters. */ if MBTEST(shellmeta (character) && ((parser_state & PST_DBLPAREN) == 0)) { @@ -2580,6 +2605,8 @@ read_token (command) parser_state &= ~PST_ALEXPNEXT; #endif /* ALIAS */ + parser_state &= ~PST_ASSIGNOK; + peek_char = shell_getc (1); if (character == peek_char) { @@ -2607,6 +2634,7 @@ read_token (command) #if defined (ALIAS) parser_state &= ~PST_ALEXPNEXT; #endif /* ALIAS */ + return (SEMI_SEMI); case '&': @@ -2674,6 +2702,7 @@ read_token (command) if MBTEST(character == '-' && (last_read_token == LESS_AND || last_read_token == GREATER_AND)) return (character); +tokword: /* Okay, if we got this far, we have to read a word. Read one, and then check it against the known ones. */ result = read_token_word (character); @@ -2687,13 +2716,14 @@ read_token (command) /* * Match a $(...) or other grouping construct. This has to handle embedded * quoted strings ('', ``, "") and nested constructs. It also must handle - * reprompting the user, if necessary, after reading a newline (unless the - * P_NONL flag is passed), and returning correct error values if it reads - * EOF. + * reprompting the user, if necessary, after reading a newline, and returning + * correct error values if it reads EOF. */ #define P_FIRSTCLOSE 0x01 #define P_ALLOWESC 0x02 #define P_DQUOTE 0x04 +#define P_COMMAND 0x08 /* parsing a command, so look for comments */ +#define P_BACKQUOTE 0x10 /* parsing a backquoted command substitution */ static char matched_pair_error; static char * @@ -2702,13 +2732,15 @@ parse_matched_pair (qc, open, close, lenp, flags) int open, close; int *lenp, flags; { - int count, ch, was_dollar; - int pass_next_character, nestlen, ttranslen, start_lineno; + int count, ch, was_dollar, in_comment, check_comment; + int pass_next_character, backq_backslash, nestlen, ttranslen, start_lineno; char *ret, *nestret, *ttrans; int retind, retsize, rflags; +/* itrace("parse_matched_pair: open = %c close = %c", open, close); */ count = 1; - pass_next_character = was_dollar = 0; + pass_next_character = backq_backslash = was_dollar = in_comment = 0; + check_comment = (flags & P_COMMAND) && qc != '`' && qc != '\'' && qc != '"' && (flags & P_DQUOTE) == 0; /* RFLAGS is the set of flags we want to pass to recursive calls. */ rflags = (qc == '"') ? P_DQUOTE : (flags & P_DQUOTE); @@ -2719,7 +2751,8 @@ parse_matched_pair (qc, open, close, lenp, flags) start_lineno = line_number; while (count) { - ch = shell_getc ((qc != '\'' || (flags & P_ALLOWESC)) && pass_next_character == 0); + ch = shell_getc (qc != '\'' && pass_next_character == 0 && backq_backslash == 0); + if (ch == EOF) { free (ret); @@ -2732,6 +2765,30 @@ parse_matched_pair (qc, open, close, lenp, flags) if (ch == '\n' && SHOULD_PROMPT ()) prompt_again (); + if (in_comment) + { + /* Add this character. */ + RESIZE_MALLOCED_BUFFER (ret, retind, 1, retsize, 64); + ret[retind++] = ch; + + if (ch == '\n') + in_comment = 0; + + continue; + } + /* Not exactly right yet, should handle shell metacharacters, too. If + any changes are made to this test, make analogous changes to subst.c: + extract_delimited_string(). */ + else if MBTEST(check_comment && in_comment == 0 && ch == '#' && (retind == 0 || ret[retind-1] == '\n' || whitespace (ret[retind - 1]))) + in_comment = 1; + + /* last char was backslash inside backquoted command substitution */ + if (backq_backslash) + { + backq_backslash = 0; + /* Placeholder for adding special characters */ + } + if (pass_next_character) /* last char was backslash */ { pass_next_character = 0; @@ -2756,11 +2813,9 @@ parse_matched_pair (qc, open, close, lenp, flags) } else if MBTEST(ch == close) /* ending delimiter */ count--; -#if 1 /* handle nested ${...} specially. */ else if MBTEST(open != close && was_dollar && open == '{' && ch == open) /* } */ count++; -#endif else if MBTEST(((flags & P_FIRSTCLOSE) == 0) && ch == open) /* nested begin */ count++; @@ -2772,6 +2827,10 @@ parse_matched_pair (qc, open, close, lenp, flags) { if MBTEST((flags & P_ALLOWESC) && ch == '\\') pass_next_character++; +#if 0 + else if MBTEST((flags & P_BACKQUOTE) && ch == '\\') + backq_backslash++; +#endif continue; } @@ -2799,9 +2858,18 @@ parse_matched_pair (qc, open, close, lenp, flags) /* Translate $'...' here. */ ttrans = ansiexpand (nestret, 0, nestlen - 1, &ttranslen); xfree (nestret); - nestret = sh_single_quote (ttrans); - free (ttrans); - nestlen = strlen (nestret); + + if ((rflags & P_DQUOTE) == 0) + { + nestret = sh_single_quote (ttrans); + free (ttrans); + nestlen = strlen (nestret); + } + else + { + nestret = ttrans; + nestlen = ttranslen; + } retind -= 2; /* back up before the $' */ } else if MBTEST(was_dollar && ch == '"' && (extended_quote || (rflags & P_DQUOTE) == 0)) @@ -2809,13 +2877,10 @@ parse_matched_pair (qc, open, close, lenp, flags) /* Locale expand $"..." here. */ ttrans = localeexpand (nestret, 0, nestlen - 1, start_lineno, &ttranslen); xfree (nestret); - nestret = (char *)xmalloc (ttranslen + 3); - nestret[0] = '"'; - strcpy (nestret + 1, ttrans); - nestret[ttranslen + 1] = '"'; - nestret[ttranslen += 2] = '\0'; + + nestret = sh_mkdoublequoted (ttrans, ttranslen, 0); free (ttrans); - nestlen = ttranslen; + nestlen = ttranslen + 2; retind -= 2; /* back up before the $" */ } @@ -2834,6 +2899,7 @@ parse_matched_pair (qc, open, close, lenp, flags) else if MBTEST(open == '"' && ch == '`') { nestret = parse_matched_pair (0, '`', '`', &nestlen, rflags); +add_nestret: if (nestret == &matched_pair_error) { free (ret); @@ -2847,29 +2913,30 @@ parse_matched_pair (qc, open, close, lenp, flags) } FREE (nestret); } - else if MBTEST(was_dollar && (ch == '(' || ch == '{' || ch == '[')) /* ) } ] */ +#if 0 + else if MBTEST(qc == '`' && (ch == '"' || ch == '\'') && in_comment == 0) + { + /* Add P_BACKQUOTE so backslash quotes the next character and + shell_getc does the right thing with \. We do this for + a measure of backwards compatibility -- it's not strictly the + right POSIX thing. */ + nestret = parse_matched_pair (0, ch, ch, &nestlen, rflags|P_BACKQUOTE); + goto add_nestret; + } +#endif + else if MBTEST(open != '`' && was_dollar && (ch == '(' || ch == '{' || ch == '[')) /* ) } ] */ /* check for $(), $[], or ${} inside quoted string. */ { if (open == ch) /* undo previous increment */ count--; if (ch == '(') /* ) */ - nestret = parse_matched_pair (0, '(', ')', &nestlen, rflags); + nestret = parse_matched_pair (0, '(', ')', &nestlen, rflags & ~P_DQUOTE); else if (ch == '{') /* } */ nestret = parse_matched_pair (0, '{', '}', &nestlen, P_FIRSTCLOSE|rflags); else if (ch == '[') /* ] */ nestret = parse_matched_pair (0, '[', ']', &nestlen, rflags); - if (nestret == &matched_pair_error) - { - free (ret); - return &matched_pair_error; - } - if (nestlen) - { - RESIZE_MALLOCED_BUFFER (ret, retind, nestlen, retsize, 64); - strcpy (ret + retind, nestret); - retind += nestlen; - } - FREE (nestret); + + goto add_nestret; } was_dollar = MBTEST(ch == '$'); } @@ -2889,8 +2956,8 @@ static int parse_dparen (c) int c; { - int cmdtyp, len, sline; - char *wval, *wv2; + int cmdtyp, sline; + char *wval; WORD_DESC *wd; #if defined (ARITH_FOR_COMMAND) @@ -2900,9 +2967,9 @@ parse_dparen (c) cmdtyp = parse_arith_cmd (&wval, 0); if (cmdtyp == 1) { - wd = make_word (wval); + wd = alloc_word_desc (); + wd->word = wval; yylval.word_list = make_word_list (wd, (WORD_LIST *)NULL); - free (wval); return (ARITH_FOR_EXPRS); } else @@ -2914,21 +2981,14 @@ parse_dparen (c) if (reserved_word_acceptable (last_read_token)) { sline = line_number; -#if 0 - cmdtyp = parse_arith_cmd (&wval, 1); -#else + cmdtyp = parse_arith_cmd (&wval, 0); -#endif if (cmdtyp == 1) /* arithmetic command */ { - wd = make_word (wval); -#if 0 - wd->flags = W_QUOTED; -#else - wd->flags = W_QUOTED|W_NOSPLIT|W_NOGLOB; -#endif + wd = alloc_word_desc (); + wd->word = wval; + wd->flags = W_QUOTED|W_NOSPLIT|W_NOGLOB|W_DQUOTE; yylval.word_list = make_word_list (wd, (WORD_LIST *)NULL); - free (wval); /* make_word copies it */ return (ARITH_CMD); } else if (cmdtyp == 0) /* nested subshell */ @@ -3147,8 +3207,11 @@ cond_term () if (tok == WORD && test_binop (yylval.word->word)) op = yylval.word; #if defined (COND_REGEXP) - else if (tok == WORD && STREQ (yylval.word->word,"=~")) - op = yylval.word; + else if (tok == WORD && STREQ (yylval.word->word, "=~")) + { + op = yylval.word; + parser_state |= PST_REGEXP; + } #endif else if (tok == '<' || tok == '>') op = make_word_from_token (tok); /* ( */ @@ -3179,6 +3242,7 @@ cond_term () /* rhs */ tok = read_token (READ); + parser_state &= ~PST_REGEXP; if (tok == WORD) { tright = make_cond_node (COND_TERM, yylval.word, (COND_COM *)NULL, (COND_COM *)NULL); @@ -3246,6 +3310,7 @@ token_is_assignment (t, i) return r; } +/* XXX - possible changes here for `+=' */ static int token_is_ident (t, i) char *t; @@ -3278,6 +3343,10 @@ read_token_word (character) /* DOLLAR_PRESENT becomes non-zero if we see a `$'. */ int dollar_present; + /* COMPOUND_ASSIGNMENT becomes non-zero if we are parsing a compound + assignment. */ + int compound_assignment; + /* QUOTED becomes non-zero if we see one of ("), ('), (`), or (\). */ int quoted; @@ -3297,7 +3366,7 @@ read_token_word (character) token_index = 0; all_digit_token = DIGIT (character); - dollar_present = quoted = pass_next_character = 0; + dollar_present = quoted = pass_next_character = compound_assignment = 0; for (;;) { @@ -3307,7 +3376,7 @@ read_token_word (character) if (pass_next_character) { pass_next_character = 0; - goto got_character; + goto got_escaped_character; } cd = current_delimiter (dstack); @@ -3343,7 +3412,7 @@ read_token_word (character) if MBTEST(shellquote (character)) { push_delimiter (dstack, character); - ttok = parse_matched_pair (character, character, character, &ttoklen, 0); + ttok = parse_matched_pair (character, character, character, &ttoklen, (character == '`') ? P_COMMAND : 0); pop_delimiter (dstack); if (ttok == &matched_pair_error) return -1; /* Bail immediately. */ @@ -3359,9 +3428,34 @@ read_token_word (character) goto next_character; } +#ifdef COND_REGEXP + /* When parsing a regexp as a single word inside a conditional command, + we need to special-case characters special to both the shell and + regular expressions. Right now, that is only '(' and '|'. */ /*)*/ + if MBTEST((parser_state & PST_REGEXP) && (character == '(' || character == '|')) /*)*/ + { + if (character == '|') + goto got_character; + + push_delimiter (dstack, character); + ttok = parse_matched_pair (cd, '(', ')', &ttoklen, 0); + pop_delimiter (dstack); + if (ttok == &matched_pair_error) + return -1; /* Bail immediately. */ + RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 2, + token_buffer_size, TOKEN_DEFAULT_GROW_SIZE); + token[token_index++] = character; + strcpy (token + token_index, ttok); + token_index += ttoklen; + FREE (ttok); + dollar_present = all_digit_token = 0; + goto next_character; + } +#endif /* COND_REGEXP */ + #ifdef EXTENDED_GLOB /* Parse a ksh-style extended pattern matching specification. */ - if (extended_glob && PATTERN_CHAR (character)) + if MBTEST(extended_glob && PATTERN_CHAR (character)) { peek_char = shell_getc (1); if MBTEST(peek_char == '(') /* ) */ @@ -3406,7 +3500,7 @@ read_token_word (character) history literally rather than causing a possibly- incorrect `;' to be added. ) */ push_delimiter (dstack, peek_char); - ttok = parse_matched_pair (cd, '(', ')', &ttoklen, 0); + ttok = parse_matched_pair (cd, '(', ')', &ttoklen, P_COMMAND); pop_delimiter (dstack); } else @@ -3442,13 +3536,14 @@ read_token_word (character) { ttrans = ansiexpand (ttok, 0, ttoklen - 1, &ttranslen); free (ttok); + /* Insert the single quotes and correctly quote any embedded single quotes (allowed because P_ALLOWESC was passed to parse_matched_pair). */ ttok = sh_single_quote (ttrans); free (ttrans); + ttranslen = strlen (ttok); ttrans = ttok; - ttranslen = strlen (ttrans); } else { @@ -3457,12 +3552,9 @@ read_token_word (character) free (ttok); /* Add the double quotes back */ - ttok = (char *)xmalloc (ttranslen + 3); - ttok[0] = '"'; - strcpy (ttok + 1, ttrans); - ttok[ttranslen + 1] = '"'; - ttok[ttranslen += 2] = '\0'; + ttok = sh_mkdoublequoted (ttrans, ttranslen, 0); free (ttrans); + ttranslen += 2; ttrans = ttok; } @@ -3515,7 +3607,7 @@ read_token_word (character) goto next_character; } /* Identify possible compound array variable assignment. */ - else if MBTEST(character == '=' && token_index > 0 && token_is_assignment (token, token_index)) + else if MBTEST(character == '=' && token_index > 0 && (assignment_acceptable (last_read_token) || (parser_state & PST_ASSIGNOK)) && token_is_assignment (token, token_index)) { peek_char = shell_getc (1); if MBTEST(peek_char == '(') /* ) */ @@ -3536,7 +3628,12 @@ read_token_word (character) token[token_index++] = ')'; FREE (ttok); all_digit_token = 0; + compound_assignment = 1; +#if 1 goto next_character; +#else + goto got_token; /* ksh93 seems to do this */ +#endif } else shell_ungetc (peek_char); @@ -3553,12 +3650,14 @@ read_token_word (character) got_character: - all_digit_token &= DIGIT (character); - dollar_present |= character == '$'; - if (character == CTLESC || character == CTLNUL) token[token_index++] = CTLESC; + got_escaped_character: + + all_digit_token &= DIGIT (character); + dollar_present |= character == '$'; + token[token_index++] = character; RESIZE_MALLOCED_BUFFER (token, token_index, 1, token_buffer_size, @@ -3630,7 +3729,9 @@ got_token: if (dollar_present) the_word->flags |= W_HASDOLLAR; if (quoted) - the_word->flags |= W_QUOTED; + the_word->flags |= W_QUOTED; /*(*/ + if (compound_assignment && token[token_index-1] == ')') + the_word->flags |= W_COMPASSIGN; /* A word is an assignment if it appears at the beginning of a simple command, or after another assignment word. This is context-dependent, so it cannot be handled in the grammar. */ @@ -3642,6 +3743,16 @@ got_token: the_word->flags |= W_NOSPLIT; } + if (command_token_position (last_read_token)) + { + struct builtin *b; + b = builtin_address_internal (token, 0); + if (b && (b->flags & ASSIGNMENT_BUILTIN)) + parser_state |= PST_ASSIGNOK; + else if (STREQ (token, "eval") || STREQ (token, "let")) + parser_state |= PST_ASSIGNOK; + } + yylval.word = the_word; result = ((the_word->flags & (W_ASSIGNMENT|W_NOSPLIT)) == (W_ASSIGNMENT|W_NOSPLIT)) @@ -3799,6 +3910,8 @@ history_delimiting_chars () return " "; return ";"; } + else if (two_tokens_ago == CASE && token_before_that == WORD && (parser_state & PST_CASESTMT)) + return " "; for (i = 0; no_semi_successors[i]; i++) { @@ -3916,7 +4029,7 @@ decode_prompt_string (string) int last_exit_value; #if defined (PROMPT_STRING_DECODE) int result_size, result_index; - int c, n; + int c, n, i; char *temp, octal_string[4]; struct tm *tm; time_t the_time; @@ -4078,7 +4191,7 @@ decode_prompt_string (string) case 'W': { /* Use the value of PWD because it is much more efficient. */ - char t_string[PATH_MAX], *t; + char t_string[PATH_MAX]; int tlen; temp = get_string_value ("PWD"); @@ -4103,7 +4216,7 @@ decode_prompt_string (string) #define ROOT_PATH(x) ((x)[0] == '/' && (x)[1] == 0) #define DOUBLE_SLASH_ROOT(x) ((x)[0] == '/' && (x)[1] == '/' && (x)[2] == 0) /* Abbreviate \W as ~ if $PWD == $HOME */ - if (c == 'W' && (((t = get_string_value ("HOME")) == 0) || STREQ (t, temp) == 0)) + if (c == 'W' && (((t = get_string_value ("HOME")) == 0) || STREQ (t, t_string) == 0)) { if (ROOT_PATH (t_string) == 0 && DOUBLE_SLASH_ROOT (t_string) == 0) { @@ -4188,9 +4301,12 @@ decode_prompt_string (string) break; } temp = (char *)xmalloc (3); - temp[0] = '\001'; - temp[1] = (c == '[') ? RL_PROMPT_START_IGNORE : RL_PROMPT_END_IGNORE; - temp[2] = '\0'; + n = (c == '[') ? RL_PROMPT_START_IGNORE : RL_PROMPT_END_IGNORE; + i = 0; + if (n == CTLESC || n == CTLNUL) + temp[i++] = CTLESC; + temp[i++] = n; + temp[i] = '\0'; goto add_string; #endif /* READLINE */ @@ -4250,7 +4366,7 @@ not_escape: if (promptvars || posixly_correct) { last_exit_value = last_command_exit_value; - list = expand_prompt_string (result, Q_DOUBLE_QUOTES); + list = expand_prompt_string (result, Q_DOUBLE_QUOTES, 0); free (result); result = string_list (list); dispose_words (list); @@ -4286,15 +4402,15 @@ yyerror (msg) } static char * -error_token_from_token (token) - int token; +error_token_from_token (tok) + int tok; { char *t; - if (t = find_token_in_alist (token, word_token_alist, 0)) + if (t = find_token_in_alist (tok, word_token_alist, 0)) return t; - if (t = find_token_in_alist (token, other_token_alist, 0)) + if (t = find_token_in_alist (tok, other_token_alist, 0)) return t; t = (char *)NULL; @@ -4582,7 +4698,7 @@ parse_string_to_word_list (s, flags, whom) line_number = orig_line_number + line_number - 1; orig_current_token = current_token; current_token = tok; - yyerror ((char *)NULL); /* does the right thing */ + yyerror (NULL); /* does the right thing */ current_token = orig_current_token; if (wl) dispose_words (wl); @@ -4628,18 +4744,21 @@ parse_compound_assignment (retlenp) int *retlenp; { WORD_LIST *wl, *rl; - int tok, orig_line_number, orig_token_size; + int tok, orig_line_number, orig_token_size, orig_last_token, assignok; char *saved_token, *ret; saved_token = token; orig_token_size = token_buffer_size; orig_line_number = line_number; + orig_last_token = last_read_token; last_read_token = WORD; /* WORD to allow reserved words here */ token = (char *)NULL; token_buffer_size = 0; + assignok = parser_state&PST_ASSIGNOK; /* XXX */ + wl = (WORD_LIST *)NULL; /* ( */ parser_state |= PST_COMPASSIGN; @@ -4657,7 +4776,7 @@ parse_compound_assignment (retlenp) if (tok == yacc_EOF) /* ( */ parser_error (orig_line_number, _("unexpected EOF while looking for matching `)'")); else - yyerror ((char *)NULL); /* does the right thing */ + yyerror(NULL); /* does the right thing */ if (wl) dispose_words (wl); wl = &parse_string_error; @@ -4682,7 +4801,8 @@ parse_compound_assignment (retlenp) jump_to_top_level (DISCARD); } - last_read_token = WORD; + last_read_token = orig_last_token; /* XXX - was WORD? */ + if (wl) { rl = REVERSE_LIST (wl, WORD_LIST *); @@ -4694,6 +4814,10 @@ parse_compound_assignment (retlenp) if (retlenp) *retlenp = (ret && *ret) ? strlen (ret) : 0; + + if (assignok) + parser_state |= PST_ASSIGNOK; + return ret; } @@ -4712,7 +4836,7 @@ save_parser_state (ps) #endif if (ps == 0) - ps = xmalloc (sizeof (sh_parser_state_t)); + ps = (sh_parser_state_t *)xmalloc (sizeof (sh_parser_state_t)); if (ps == 0) return ((sh_parser_state_t *)NULL);