Esempio n. 1
0
int parser_t::eval_block_node(node_offset_t node_idx, const io_chain_t &io,
                              enum block_type_t block_type) {
    // Paranoia. It's a little frightening that we're given only a node_idx and we interpret this in
    // the topmost execution context's tree. What happens if two trees were to be interleaved?
    // Fortunately that cannot happen (yet); in the future we probably want some sort of reference
    // counted trees.
    parse_execution_context_t *ctx = execution_contexts.back();
    assert(ctx != NULL);

    CHECK_BLOCK(1);

    // Handle cancellation requests. If our block stack is currently empty, then we already did
    // successfully cancel (or there was nothing to cancel); clear the flag. If our block stack is
    // not empty, we are still in the process of cancelling; refuse to evaluate anything.
    if (this->cancellation_requested) {
        if (!block_stack.empty()) {
            return 1;
        }
        this->cancellation_requested = false;
    }

    // Only certain blocks are allowed.
    if ((block_type != TOP) && (block_type != SUBST)) {
        debug(1, INVALID_SCOPE_ERR_MSG, parser_t::get_block_desc(block_type));
        bugreport();
        return 1;
    }

    job_reap(0);  // not sure why we reap jobs here

    /* Start it up */
    const block_t *const start_current_block = current_block();
    block_t *scope_block = new scope_block_t(block_type);
    this->push_block(scope_block);
    int result = ctx->eval_node_at_offset(node_idx, scope_block, io);

    // Clean up the block stack.
    this->pop_block();
    while (start_current_block != current_block()) {
        if (current_block() == NULL) {
            debug(0, _(L"End of block mismatch. Program terminating."));
            bugreport();
            FATAL_EXIT();
            break;
        }
        this->pop_block();
    }

    job_reap(0);  // reap again

    return result;
}
Esempio n. 2
0
/**
   Handle interruptions to key reading by reaping finshed jobs and
   propagating the interrupt to the reader.
*/
static int interrupt_handler()
{
	/*
	  Fire any pending events
	*/
	event_fire( 0 );	
	
	/*
	  Reap stray processes, including printing exit status messages
	*/
	if( job_reap( 1 ) )
		reader_repaint_needed();
	
	/*
	  Tell the reader an event occured
	*/
	if( reader_interrupted() )
	{
		/*
		  Return 3, i.e. the character read by a Control-C.
		*/
		return 3;
	}

	return R_NULL;	
}
Esempio n. 3
0
File: exec.c Progetto: CodeMonk/fish
static void internal_exec_helper( const wchar_t *def, 
								 int block_type,
								 io_data_t *io )
{
	io_data_t *io_internal = io_transmogrify( io );
	int is_block_old=is_block;
	is_block=1;
	
	/*
	  Did the transmogrification fail - if so, set error status and return
	*/
	if( io && !io_internal )
	{
		proc_set_last_status( STATUS_EXEC_FAIL );
		return;
	}
	
	signal_unblock();
	
	eval( def, io_internal, block_type );		
	
	signal_block();
	
	io_untransmogrify( io, io_internal );
	job_reap( 0 );
	is_block=is_block_old;
}
Esempio n. 4
0
int parser_t::eval_node(parsed_source_ref_t ps, tnode_t<T> node, const io_chain_t &io,
                        enum block_type_t block_type) {
    static_assert(
        std::is_same<T, grammar::statement>::value || std::is_same<T, grammar::job_list>::value,
        "Unexpected node type");
    CHECK_BLOCK(1);

    // Handle cancellation requests. If our block stack is currently empty, then we already did
    // successfully cancel (or there was nothing to cancel); clear the flag. If our block stack is
    // not empty, we are still in the process of cancelling; refuse to evaluate anything.
    if (this->cancellation_requested) {
        if (!block_stack.empty()) {
            return 1;
        }
        this->cancellation_requested = false;
    }

    // Only certain blocks are allowed.
    if ((block_type != TOP) && (block_type != SUBST)) {
        debug(1, INVALID_SCOPE_ERR_MSG, parser_t::get_block_desc(block_type));
        bugreport();
        return 1;
    }

    job_reap(0);  // not sure why we reap jobs here

    // Start it up
    scope_block_t *scope_block = this->push_block<scope_block_t>(block_type);

    // Create and set a new execution context.
    using exc_ctx_ref_t = std::unique_ptr<parse_execution_context_t>;
    scoped_push<exc_ctx_ref_t> exc(&execution_context,
                                   make_unique<parse_execution_context_t>(ps, this));
    int result = execution_context->eval_node(node, scope_block, io);
    exc.restore();
    this->pop_block(scope_block);

    job_reap(0);  // reap again
    return result;
}
Esempio n. 5
0
void internal_exec_helper(parser_t &parser, parsed_source_ref_t parsed_source, tnode_t<T> node,
                          const io_chain_t &ios) {
    assert(parsed_source && node && "exec_helper missing source or without node");

    io_chain_t morphed_chain;
    std::vector<int> opened_fds;
    bool transmorgrified = io_transmogrify(ios, &morphed_chain, &opened_fds);

    // Did the transmogrification fail - if so, set error status and return.
    if (!transmorgrified) {
        proc_set_last_status(STATUS_EXEC_FAIL);
        return;
    }

    parser.eval_node(parsed_source, node, morphed_chain, TOP);

    morphed_chain.clear();
    io_cleanup_fds(opened_fds);
    job_reap(0);
}