aboutsummaryrefslogtreecommitdiffstats
path: root/parse.y
diff options
context:
space:
mode:
Diffstat (limited to 'parse.y')
-rw-r--r--parse.y57
1 files changed, 48 insertions, 9 deletions
diff --git a/parse.y b/parse.y
index eca168e..24f709c 100644
--- a/parse.y
+++ b/parse.y
@@ -786,11 +786,14 @@ timespec: TIME
#define TOKEN_DEFAULT_GROW_SIZE 512
/* Shell meta-characters that, when unquoted, separate words. */
-#define shellmeta(c) (strchr ("()<>;&|", (c)) != 0)
-#define shellbreak(c) (strchr ("()<>;&| \t\n", (c)) != 0)
+#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;
@@ -1467,6 +1470,10 @@ STRING_INT_ALIST word_token_alist[] = {
{ (char *)NULL, 0}
};
+/* 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. */
+
/* 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. */
@@ -1919,6 +1926,11 @@ time_command_acceptable ()
case AND_AND:
case OR_OR:
case '&':
+ case DO:
+ case THEN:
+ case ELSE:
+ case '{':
+ case '(':
return 1;
default:
return 0;
@@ -2022,7 +2034,7 @@ special_case_tokens (token)
#endif
#if defined (COMMAND_TIMING)
- if (STREQ (token, "time") && time_command_acceptable ())
+ if (STREQ (token, "time") && ((parser_state & PST_CASEPAT) == 0) && time_command_acceptable ())
return (TIME);
#endif /* COMMAND_TIMING */
@@ -2288,6 +2300,9 @@ read_token (command)
quoted strings ('', ``, "") and nested constructs. It also must handle
reprompting the user, if necessary, after reading a newline, and returning
correct error values if it reads EOF. */
+
+#define P_FIRSTCLOSE 0x01
+
static char matched_pair_error;
static char *
parse_matched_pair (qc, open, close, lenp, flags)
@@ -2347,7 +2362,7 @@ parse_matched_pair (qc, open, close, lenp, flags)
}
else if (ch == close) /* ending delimiter */
count--;
- else if (ch == open) /* nested begin */
+ else if (((flags & P_FIRSTCLOSE) == 0) && ch == open) /* nested begin */
count++;
/* Add this character. */
@@ -2409,7 +2424,7 @@ parse_matched_pair (qc, open, close, lenp, flags)
if (ch == '(') /* ) */
nestret = parse_matched_pair (0, '(', ')', &nestlen, 0);
else if (ch == '{') /* } */
- nestret = parse_matched_pair (0, '{', '}', &nestlen, 0);
+ nestret = parse_matched_pair (0, '{', '}', &nestlen, P_FIRSTCLOSE);
else if (ch == '[') /* ] */
nestret = parse_matched_pair (0, '[', ']', &nestlen, 0);
if (nestret == &matched_pair_error)
@@ -2787,7 +2802,7 @@ read_token_word (character)
((peek_char == '{' || peek_char == '[') && character == '$')) /* ) ] } */
{
if (peek_char == '{') /* } */
- ttok = parse_matched_pair (cd, '{', '}', &ttoklen, 0);
+ ttok = parse_matched_pair (cd, '{', '}', &ttoklen, P_FIRSTCLOSE);
else if (peek_char == '(') /* ) */
{
/* XXX - push and pop the `(' as a delimiter for use by
@@ -2841,6 +2856,23 @@ read_token_word (character)
all_digits = 0;
goto next_character;
}
+ /* This could eventually be extended to recognize all of the
+ shell's single-character parameter expansions, and set flags.*/
+ else if (character == '$' && peek_char == '$')
+ {
+ ttok = xmalloc (3);
+ ttok[0] = ttok[1] = '$';
+ ttok[2] = '\0';
+ RESIZE_MALLOCED_BUFFER (token, token_index, 3,
+ token_buffer_size,
+ TOKEN_DEFAULT_GROW_SIZE);
+ strcpy (token + token_index, ttok);
+ token_index += 2;
+ dollar_present = 1;
+ all_digits = 0;
+ FREE (ttok);
+ goto next_character;
+ }
else
shell_ungetc (peek_char);
}
@@ -2855,6 +2887,11 @@ read_token_word (character)
ttok = parse_matched_pair (cd, '(', ')', &ttoklen, 0);
if (ttok == &matched_pair_error)
return -1; /* Bail immediately. */
+ if (ttok[0] == '(') /* ) */
+ {
+ FREE (ttok);
+ return -1;
+ }
RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 2,
token_buffer_size,
TOKEN_DEFAULT_GROW_SIZE);
@@ -3473,9 +3510,11 @@ decode_prompt_string (string)
goto add_string;
case '$':
- temp = xmalloc (2);
- temp[0] = current_user.euid == 0 ? '#' : '$';
- temp[1] = '\0';
+ t = temp = xmalloc (3);
+ if ((promptvars || posixly_correct) && (current_user.euid != 0))
+ *t++ = '\\';
+ *t++ = current_user.euid == 0 ? '#' : '$';
+ *t = '\0';
goto add_string;
#if defined (READLINE)