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; }
/** 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; }
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; }
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; }
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); }