static int reserved_word_acceptable ();
static int read_token ();
static int yylex ();
+static int parse_arith_cmd ();
static int read_token_word ();
static void discard_parser_constructs ();
static void report_syntax_error ();
static void handle_eof_input_unit ();
static void prompt_again ();
+#if 0
static void reset_readline_prompt ();
+#endif
static void print_prompt ();
+extern int yyerror ();
+
/* Default prompt strings */
char *primary_prompt = PPROMPT;
char *secondary_prompt = SPROMPT;
{ $$ = $1; }
;
-for_command: FOR WORD newline_list DO list DONE
+for_command: FOR WORD newline_list DO compound_list DONE
{ $$ = make_for_command ($2, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), $5); }
- | FOR WORD newline_list '{' list '}'
+ | FOR WORD newline_list '{' compound_list '}'
{ $$ = make_for_command ($2, add_string_to_list ("$@", (WORD_LIST *)NULL), $5); }
- | FOR WORD ';' newline_list DO list DONE
+ | FOR WORD ';' newline_list DO compound_list DONE
{ $$ = make_for_command ($2, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), $6); }
- | FOR WORD ';' newline_list '{' list '}'
+ | FOR WORD ';' newline_list '{' compound_list '}'
{ $$ = make_for_command ($2, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), $6); }
- | FOR WORD newline_list IN word_list list_terminator newline_list DO list DONE
+ | FOR WORD newline_list IN word_list list_terminator newline_list DO compound_list DONE
{ $$ = make_for_command ($2, REVERSE_LIST ($5, WORD_LIST *), $9); }
- | FOR WORD newline_list IN word_list list_terminator newline_list '{' list '}'
+ | FOR WORD newline_list IN word_list list_terminator newline_list '{' compound_list '}'
{ $$ = make_for_command ($2, REVERSE_LIST ($5, WORD_LIST *), $9); }
;
/* Initial size to allocate for tokens, and the
amount to grow them by. */
+#define TOKEN_DEFAULT_INITIAL_SIZE 496
#define TOKEN_DEFAULT_GROW_SIZE 512
/* Shell meta-characters that, when unquoted, separate words. */
void
init_yy_io (get, unget, type, name, location)
Function *get, *unget;
- int type;
+ enum stream_type type;
char *name;
INPUT_STREAM location;
{
temp->next = pushed_string_list;
pushed_string_list = temp;
- ap->flags |= AL_BEINGEXPANDED;
+ if (ap)
+ ap->flags |= AL_BEINGEXPANDED;
shell_input_line = s;
shell_input_line_size = strlen (s);
t = pushed_string_list;
pushed_string_list = pushed_string_list->next;
- t->expander->flags &= ~AL_BEINGEXPANDED;
+ if (t->expander)
+ t->expander->flags &= ~AL_BEINGEXPANDED;
free ((char *)t);
}
# if defined (BANG_HISTORY)
history_expansion_inhibited = old_hist;
# endif
-
- free (shell_input_line);
- shell_input_line = expansions;
- shell_input_line_len = shell_input_line ?
- strlen (shell_input_line) :
- 0;
- if (!shell_input_line_len)
- 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. */
- shell_input_line_size = shell_input_line_len;
+ if (expansions != shell_input_line)
+ {
+ free (shell_input_line);
+ shell_input_line = expansions;
+ shell_input_line_len = shell_input_line ?
+ strlen (shell_input_line) : 0;
+ if (!shell_input_line_len)
+ 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. */
+ shell_input_line_size = shell_input_line_len;
+ }
}
/* XXX - this is grotesque */
else if (remember_on_history && shell_input_line &&
if (last_lastarg)
last_lastarg = savestring (last_lastarg);
- parse_and_execute (savestring (command), "PROMPT_COMMAND", 0);
+ parse_and_execute (savestring (command), "PROMPT_COMMAND", SEVAL_NONINT|SEVAL_NOHIST);
last_shell_builtin = temp_last;
this_shell_builtin = temp_this;
{
result = token_to_read;
if (token_to_read == WORD || token_to_read == ASSIGNMENT_WORD)
- yylval.word = word_desc_to_read;
+ {
+ yylval.word = word_desc_to_read;
+ word_desc_to_read = (WORD_DESC *)NULL;
+ }
token_to_read = 0;
return (result);
}
case '(': /* ) */
if (reserved_word_acceptable (last_read_token))
{
- parser_state |= PST_DBLPAREN;
- yylval.word = make_word ("let");
- return (WORD);
+ int cmdtyp, sline;
+ char *wval;
+
+ sline = line_number;
+ cmdtyp = parse_arith_cmd (&wval);
+ if (cmdtyp == 1) /* arithmetic command */
+ {
+ word_desc_to_read = make_word (wval);
+ word_desc_to_read->flags = W_QUOTED;
+ token_to_read = WORD;
+ free (wval);
+ yylval.word = make_word ("let");
+ return (WORD);
+ }
+ else if (cmdtyp == 0) /* nested subshell */
+ {
+ push_string (wval, 0, (alias_t *)NULL);
+ if ((parser_state & PST_CASEPAT) == 0)
+ parser_state |= PST_SUBSHELL;
+ return (character);
+ }
+ else /* ERROR */
+ return -1;
}
break;
#endif
return ret;
}
+#if defined (DPAREN_ARITHMETIC)
+/* We've seen a `(('. Look for the matching `))'. If we get it, return 1.
+ If not, assume it's a nested subshell for backwards compatibility and
+ return 0. In any case, put the characters we've consumed into a locally-
+ allocated buffer and make *ep point to that buffer. Return -1 on an
+ error, for example EOF. */
+static int
+parse_arith_cmd (ep)
+ char **ep;
+{
+ int exp_lineno, rval, c;
+ char *ttok, *token;
+ int ttoklen;
+
+ exp_lineno = line_number;
+ ttok = parse_matched_pair (0, '(', ')', &ttoklen, 0);
+ rval = 1;
+ if (ttok == &matched_pair_error)
+ return -1;
+ /* Check that the next character is the closing right paren. If
+ not, this is a syntax error. ( */
+ if ((c = shell_getc (0)) != ')')
+ rval = 0;
+
+ token = xmalloc(ttoklen + 4);
+
+ /* (( ... )) -> "..." */
+ token[0] = (rval == 1) ? '"' : '(';
+ strncpy (token + 1, ttok, ttoklen - 1); /* don't copy the final `)' */
+ if (rval == 1)
+ {
+ token[ttoklen] = '"';
+ token[ttoklen+1] = '\0';
+ }
+ else
+ {
+ token[ttoklen] = ')';
+ token[ttoklen+1] = c;
+ token[ttoklen+2] = '\0';
+ }
+ *ep = token;
+ FREE (ttok);
+ return rval;
+}
+#endif /* DPAREN_ARITHMETIC */
+
static int
read_token_word (character)
int character;
char *ttok, *ttrans;
int ttoklen, ttranslen;
- if (token_buffer_size < TOKEN_DEFAULT_GROW_SIZE)
- {
- FREE (token);
- token = xmalloc (token_buffer_size = TOKEN_DEFAULT_GROW_SIZE);
- }
+ if (token_buffer_size < TOKEN_DEFAULT_INITIAL_SIZE)
+ token = xrealloc (token, token_buffer_size = TOKEN_DEFAULT_INITIAL_SIZE);
token_index = 0;
all_digits = digit (character);
}
}
-#if defined (DPAREN_ARITHMETIC)
- /* Parse a ksh-style ((...)) expression. */
- if (parser_state & PST_DBLPAREN)
- {
- int exp_lineno;
-
- /* If we've already consumed a right paren that should be part of
- the expression, push it back so the paren matching code won't
- return prematurely. */
- if (character == '(') /* ) */
- shell_ungetc (character);
- exp_lineno = line_number;
- ttok = parse_matched_pair (0, '(', ')', &ttoklen, 0);
- parser_state &= ~PST_DBLPAREN;
- if (ttok == &matched_pair_error)
- return -1;
- /* Check that the next character is the closing right paren. If
- not, this is a syntax error. ( */
- if (shell_getc (0) != ')')
- {
- FREE (ttok); /* ( */
- parser_error (exp_lineno, "missing closing `)' for arithmetic expression");
- return -1;
- }
- RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 4,
- token_buffer_size, TOKEN_DEFAULT_GROW_SIZE);
- token[token_index++] = '"';
- if (character != '(') /* ) */
- token[token_index++] = character;
- strncpy (token + token_index, ttok, ttoklen - 1);
- token_index += ttoklen - 1;
- token[token_index++] = '"';
- FREE (ttok);
- dollar_present = all_digits = 0;
- quoted = 1;
- goto got_token;
- }
-#endif /* DPAREN_ARITHMETIC */
-
/* Parse a matched pair of quote characters. */
if (shellquote (character))
{
if (peek_char == '{') /* } */
ttok = parse_matched_pair (cd, '{', '}', &ttoklen, 0);
else if (peek_char == '(') /* ) */
- ttok = parse_matched_pair (cd, '(', ')', &ttoklen, 0);
+ {
+ /* XXX - push and pop the `(' as a delimiter for use by
+ the command-oriented-history code. This way newlines
+ appearing in the $(...) string get added to the
+ history literally rather than causing a possibly-
+ incorrect `;' to be added. */
+ push_delimiter (dstack, peek_char);
+ ttok = parse_matched_pair (cd, '(', ')', &ttoklen, 0);
+ pop_delimiter (dstack);
+ }
else
ttok = parse_matched_pair (cd, '[', ']', &ttoklen, 0);
if (ttok == &matched_pair_error)
if (*temp)
{
- t = ansicstr (temp, tlen, (int *)NULL);
+ t = ansicstr (temp, tlen, (int *)NULL, lenp);
free (temp);
- if (lenp)
- *lenp = strlen (t);
return (t);
}
else
\[ begin a sequence of non-printing chars
\] end a sequence of non-printing chars
*/
-#define PROMPT_GROWTH 50
+#define PROMPT_GROWTH 48
char *
decode_prompt_string (string)
char *string;