Bash-4.3 distribution sources and documentation
This commit is contained in:
parent
4539d736f1
commit
ac50fbac37
497 changed files with 129395 additions and 87598 deletions
|
@ -1,6 +1,6 @@
|
|||
/* evalstring.c - evaluate a string as one or more shell commands. */
|
||||
|
||||
/* Copyright (C) 1996-2010 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1996-2012 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
@ -61,7 +61,7 @@ extern int errno;
|
|||
#define IS_BUILTIN(s) (builtin_address_internal(s, 0) != (struct builtin *)NULL)
|
||||
|
||||
extern int indirection_level, subshell_environment;
|
||||
extern int line_number;
|
||||
extern int line_number, line_number_for_err_trap;
|
||||
extern int current_token, shell_eof_token;
|
||||
extern int last_command_exit_value;
|
||||
extern int running_trap;
|
||||
|
@ -69,7 +69,9 @@ extern int loop_level;
|
|||
extern int executing_list;
|
||||
extern int comsub_ignore_return;
|
||||
extern int posixly_correct;
|
||||
extern int return_catch_flag, return_catch_value;
|
||||
extern sh_builtin_func_t *this_shell_builtin;
|
||||
extern char *the_printed_command_except_trap;
|
||||
|
||||
int parse_and_execute_level = 0;
|
||||
|
||||
|
@ -86,6 +88,14 @@ set_history_remembering ()
|
|||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
restore_lastcom (x)
|
||||
char *x;
|
||||
{
|
||||
FREE (the_printed_command_except_trap);
|
||||
the_printed_command_except_trap = x;
|
||||
}
|
||||
|
||||
/* How to force parse_and_execute () to clean up after itself. */
|
||||
void
|
||||
parse_and_execute_cleanup ()
|
||||
|
@ -108,7 +118,7 @@ parse_prologue (string, flags, tag)
|
|||
int flags;
|
||||
char *tag;
|
||||
{
|
||||
char *orig_string;
|
||||
char *orig_string, *lastcom;
|
||||
int x;
|
||||
|
||||
orig_string = string;
|
||||
|
@ -118,6 +128,7 @@ parse_prologue (string, flags, tag)
|
|||
unwind_protect_jmp_buf (top_level);
|
||||
unwind_protect_int (indirection_level);
|
||||
unwind_protect_int (line_number);
|
||||
unwind_protect_int (line_number_for_err_trap);
|
||||
unwind_protect_int (loop_level);
|
||||
unwind_protect_int (executing_list);
|
||||
unwind_protect_int (comsub_ignore_return);
|
||||
|
@ -140,8 +151,17 @@ parse_prologue (string, flags, tag)
|
|||
x = get_current_prompt_level ();
|
||||
add_unwind_protect (set_current_prompt_level, x);
|
||||
}
|
||||
|
||||
|
||||
if (the_printed_command_except_trap)
|
||||
{
|
||||
lastcom = savestring (the_printed_command_except_trap);
|
||||
add_unwind_protect (restore_lastcom, lastcom);
|
||||
}
|
||||
|
||||
add_unwind_protect (pop_stream, (char *)NULL);
|
||||
if (parser_expanding_alias ())
|
||||
add_unwind_protect (parser_restore_alias, (char *)NULL);
|
||||
|
||||
if (orig_string && ((flags & SEVAL_NOFREE) == 0))
|
||||
add_unwind_protect (xfree, orig_string);
|
||||
end_unwind_frame ();
|
||||
|
@ -175,6 +195,7 @@ parse_and_execute (string, from_file, flags)
|
|||
int code, lreset;
|
||||
volatile int should_jump_to_top_level, last_result;
|
||||
COMMAND *volatile command;
|
||||
volatile sigset_t pe_sigmask;
|
||||
|
||||
parse_prologue (string, flags, PE_TAG);
|
||||
|
||||
|
@ -182,11 +203,21 @@ parse_and_execute (string, from_file, flags)
|
|||
|
||||
lreset = flags & SEVAL_RESETLINE;
|
||||
|
||||
#if defined (HAVE_POSIX_SIGNALS)
|
||||
/* If we longjmp and are going to go on, use this to restore signal mask */
|
||||
sigemptyset (&pe_sigmask);
|
||||
sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &pe_sigmask);
|
||||
#endif
|
||||
|
||||
/* Reset the line number if the caller wants us to. If we don't reset the
|
||||
line number, we have to subtract one, because we will add one just
|
||||
before executing the next command (resetting the line number sets it to
|
||||
0; the first line number is 1). */
|
||||
push_stream (lreset);
|
||||
if (parser_expanding_alias ())
|
||||
/* push current shell_input_line */
|
||||
parser_save_alias ();
|
||||
|
||||
if (lreset == 0)
|
||||
line_number--;
|
||||
|
||||
|
@ -209,15 +240,28 @@ parse_and_execute (string, from_file, flags)
|
|||
/* Provide a location for functions which `longjmp (top_level)' to
|
||||
jump to. This prevents errors in substitution from restarting
|
||||
the reader loop directly, for example. */
|
||||
code = setjmp (top_level);
|
||||
code = setjmp_nosigs (top_level);
|
||||
|
||||
if (code)
|
||||
{
|
||||
should_jump_to_top_level = 0;
|
||||
switch (code)
|
||||
{
|
||||
case FORCE_EOF:
|
||||
case ERREXIT:
|
||||
/* variable_context -> 0 is what eval.c:reader_loop() does in
|
||||
these circumstances. Don't bother with cleanup here because
|
||||
we don't want to run the function execution cleanup stuff
|
||||
that will cause pop_context and other functions to run.
|
||||
XXX - change that if we want the function context to be
|
||||
unwound. */
|
||||
if (exit_immediately_on_error && variable_context)
|
||||
{
|
||||
discard_unwind_frame ("pe_dispose");
|
||||
variable_context = 0; /* not in a function */
|
||||
}
|
||||
should_jump_to_top_level = 1;
|
||||
goto out;
|
||||
case FORCE_EOF:
|
||||
case EXITPROG:
|
||||
if (command)
|
||||
run_unwind_frame ("pe_dispose");
|
||||
|
@ -239,6 +283,9 @@ parse_and_execute (string, from_file, flags)
|
|||
{
|
||||
#if 0
|
||||
dispose_command (command); /* pe_dispose does this */
|
||||
#endif
|
||||
#if defined (HAVE_POSIX_SIGNALS)
|
||||
sigprocmask (SIG_SETMASK, &pe_sigmask, (sigset_t *)NULL);
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
@ -308,7 +355,8 @@ parse_and_execute (string, from_file, flags)
|
|||
command->value.Simple->words == 0 &&
|
||||
command->value.Simple->redirects &&
|
||||
command->value.Simple->redirects->next == 0 &&
|
||||
command->value.Simple->redirects->instruction == r_input_direction)
|
||||
command->value.Simple->redirects->instruction == r_input_direction &&
|
||||
command->value.Simple->redirects->redirector.dest == 0)
|
||||
{
|
||||
int r;
|
||||
r = cat_file (command->value.Simple->redirects);
|
||||
|
@ -317,7 +365,6 @@ parse_and_execute (string, from_file, flags)
|
|||
else
|
||||
last_result = execute_command_internal
|
||||
(command, 0, NO_PIPE, NO_PIPE, bitmap);
|
||||
|
||||
dispose_command (command);
|
||||
dispose_fd_bitmap (bitmap);
|
||||
discard_unwind_frame ("pe_dispose");
|
||||
|
@ -377,15 +424,26 @@ parse_string (string, from_file, flags, endp)
|
|||
volatile int should_jump_to_top_level;
|
||||
COMMAND *volatile command, *oglobal;
|
||||
char *ostring;
|
||||
volatile sigset_t ps_sigmask;
|
||||
|
||||
parse_prologue (string, flags, PS_TAG);
|
||||
|
||||
#if defined (HAVE_POSIX_SIGNALS)
|
||||
/* If we longjmp and are going to go on, use this to restore signal mask */
|
||||
sigemptyset (&ps_sigmask);
|
||||
sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &ps_sigmask);
|
||||
#endif
|
||||
|
||||
/* itrace("parse_string: `%s'", string); */
|
||||
/* Reset the line number if the caller wants us to. If we don't reset the
|
||||
line number, we have to subtract one, because we will add one just
|
||||
before executing the next command (resetting the line number sets it to
|
||||
0; the first line number is 1). */
|
||||
push_stream (0);
|
||||
|
||||
if (parser_expanding_alias ())
|
||||
/* push current shell_input_line */
|
||||
parser_save_alias ();
|
||||
|
||||
code = should_jump_to_top_level = 0;
|
||||
oglobal = global_command;
|
||||
ostring = string;
|
||||
|
@ -402,7 +460,7 @@ parse_string (string, from_file, flags, endp)
|
|||
|
||||
/* Provide a location for functions which `longjmp (top_level)' to
|
||||
jump to. */
|
||||
code = setjmp (top_level);
|
||||
code = setjmp_nosigs (top_level);
|
||||
|
||||
if (code)
|
||||
{
|
||||
|
@ -424,6 +482,9 @@ itrace("parse_string: longjmp executed: code = %d", code);
|
|||
goto out;
|
||||
|
||||
default:
|
||||
#if defined (HAVE_POSIX_SIGNALS)
|
||||
sigprocmask (SIG_SETMASK, &ps_sigmask, (sigset_t *)NULL);
|
||||
#endif
|
||||
command_error ("parse_string", CMDERR_BADJUMP, code, 0);
|
||||
break;
|
||||
}
|
||||
|
@ -506,3 +567,49 @@ cat_file (r)
|
|||
|
||||
return (rval);
|
||||
}
|
||||
|
||||
int
|
||||
evalstring (string, from_file, flags)
|
||||
char *string;
|
||||
const char *from_file;
|
||||
int flags;
|
||||
{
|
||||
volatile int r, rflag, rcatch;
|
||||
|
||||
rcatch = 0;
|
||||
rflag = return_catch_flag;
|
||||
/* If we are in a place where `return' is valid, we have to catch
|
||||
`eval "... return"' and make sure parse_and_execute cleans up. Then
|
||||
we can trampoline to the previous saved return_catch location. */
|
||||
if (rflag)
|
||||
{
|
||||
begin_unwind_frame ("evalstring");
|
||||
|
||||
unwind_protect_int (return_catch_flag);
|
||||
unwind_protect_jmp_buf (return_catch);
|
||||
|
||||
return_catch_flag++; /* increment so we have a counter */
|
||||
rcatch = setjmp_nosigs (return_catch);
|
||||
}
|
||||
|
||||
if (rcatch)
|
||||
{
|
||||
parse_and_execute_cleanup ();
|
||||
r = return_catch_value;
|
||||
}
|
||||
else
|
||||
/* Note that parse_and_execute () frees the string it is passed. */
|
||||
r = parse_and_execute (string, from_file, flags);
|
||||
|
||||
if (rflag)
|
||||
{
|
||||
run_unwind_frame ("evalstring");
|
||||
if (rcatch && return_catch_flag)
|
||||
{
|
||||
return_catch_value = r;
|
||||
longjmp (return_catch, 1);
|
||||
}
|
||||
}
|
||||
|
||||
return (r);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue