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; }