Exemple #1
0
void trans_code(void)
{
	mval		dummy;
	int		level2go;
	DCL_THREADGBL_ACCESS;

	SETUP_THREADGBL_ACCESS;
	if (SFT_ZINTR & proc_act_type)
	{	/* Need different translator EP */
		jobinterrupt_process();
		return;
	}
	assert(err_act);
	if (stringpool.base != rts_stringpool.base)
		stringpool = rts_stringpool;
	assert(SFT_ZTRAP == proc_act_type || SFT_DEV_ACT == proc_act_type);
	/* The frame_pointer->mpc of error-causing M routine should always be set
	 * to 'error_return' irrespective of the validity of $etrap code to make sure
	 * the error-occuring frame is always unwound and the new error is rethrown
	 * at one level below
	 */
	if (IS_ETRAP)
		SET_ERROR_FRAME(frame_pointer);	/* reset error_frame to point to frame_pointer */
	if (!(ztrap_form & ZTRAP_CODE) && !IS_ETRAP && POP_SPECIFIED)
	{
		GOLEVEL(level2go, TRUE);
	}
	dummy.mvtype = MV_STR;
	dummy.str = *err_act;
	TREF(trans_code_pop) = push_mval(&dummy);

	ESTABLISH(trans_code_ch);
	op_commarg(TREF(trans_code_pop), ((ztrap_form & ZTRAP_CODE) || IS_ETRAP) ? indir_linetail : indir_goto);
	REVERT;
#	ifdef UNIX
	if (NULL != gtm_err_dev)
	{
		remove_rms(gtm_err_dev);
		gtm_err_dev = NULL;
	}
#	endif
	trans_code_finish();
	return;
}
void error_return(void)
{
	int		parent_level;
	stack_frame	*curframe, *cur_counted_frame, *parent_counted_frame;
	boolean_t	rethrow_needed = FALSE, dev_act_err;

	DBGEHND((stderr, "error_return: Entered\n"));
	assert((frame_pointer->flags & SFF_ETRAP_ERR) || (error_frame == frame_pointer));
	/* Determine counted frame at the current $zlevel */
	for (curframe = frame_pointer; (NULL != curframe) && !(curframe->type & SFT_COUNT) && !BASE_FRAME(curframe);
			curframe = curframe->old_frame_pointer)
		;
	cur_counted_frame = curframe;
	NULLIFY_ERROR_FRAME;	/* reset error_frame */
	dev_act_err = ((NULL != cur_counted_frame) && (cur_counted_frame->flags & SFF_ETRAP_ERR)
		&& (cur_counted_frame->flags & SFF_DEV_ACT_ERR));
	/* If the top level error is a device exception error, we do not want to unwind upto the parent frame but instead
	 * rethrow the error at the current level and use $ztrap/$etrap exception handling. In case even that fails,
	 * we will come again to error_return at which point, we will do the unwind upto the parent frame.
	 */
	if (!dev_act_err && (NULL != curframe))		/* Determine counted frame at the parent  $zlevel */
		for (curframe = curframe->old_frame_pointer;
		    (NULL != curframe) && !(curframe->type & SFT_COUNT) && !BASE_FRAME(curframe);
		    curframe = curframe->old_frame_pointer)
			;
	parent_counted_frame = curframe;
	/* Exit if we are at the bottom of the stack */
	parent_level = dollar_zlevel() - 1;
	if ((NULL == parent_counted_frame) || (1 > parent_level))
		EXIT(dollar_ecode.error_last_ecode);
	assert(parent_level > 0);
	if (dev_act_err || (!BASE_FRAME(parent_counted_frame) && dollar_ecode.index))
		rethrow_needed = TRUE;
	DBGEHND((stderr, "error_return: rethrow_needed: %d  dev_act_err: %d\n", rethrow_needed, dev_act_err));
	if (!dev_act_err)
	{
		if (parent_counted_frame->type & SFT_DM)
		{	/* hack to retain SFT_DM frame from being unwound by golevel */
			parent_counted_frame->type |= SFT_COUNT;
			GOLEVEL(parent_level + 1, FALSE);
			parent_counted_frame->type &= ~SFT_COUNT;
			assert(parent_counted_frame->type & SFT_DM);
		} else
			GOLEVEL(parent_level, FALSE);
		/* Check that we have unwound exactly upto the parent counted frame. */
		assert(parent_counted_frame == frame_pointer);
	} else
	{
		GOLEVEL(parent_level + 1, FALSE);
		/* Check that we have unwound exactly upto the current counted frame. */
		assert(cur_counted_frame == frame_pointer);
	}
	assert(!proc_act_type);
	if (rethrow_needed)
	{
		rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_REPEATERROR);
		assert(FALSE);	/* the previous rts_error() should not return */
	}
	/* zero the error device just to be safe */
	assert(NULL == gtm_err_dev);
	gtm_err_dev = NULL;
}