void trans_code_cleanup(void) { stack_frame *fp, *fpprev; uint4 errmsg; DCL_THREADGBL_ACCESS; SETUP_THREADGBL_ACCESS; assert(!(SFT_ZINTR & proc_act_type)); /* With no extra ztrap frame being pushed onto stack, we may miss error(s) * during trans_code if we don't check proc_act_type in addition to * frame_pointer->type below. */ if (SFT_ZTRAP == proc_act_type) { if (0 < dollar_ztrap.str.len) errmsg = ERR_ERRWZTRAP; else errmsg = ERR_ERRWETRAP; } else if (SFT_DEV_ACT == proc_act_type) errmsg = ERR_ERRWIOEXC; else errmsg = 0; proc_act_type = 0; if (TREF(compile_time)) { TREF(compile_time) = FALSE; if (stringpool.base != rts_stringpool.base) stringpool = rts_stringpool; } for (fp = frame_pointer; fp; fp = fpprev) { fpprev = fp->old_frame_pointer; # ifdef GTM_TRIGGER if (SFT_TRIGR & fpprev->type) fpprev = *(stack_frame **)(fpprev + 1); # endif if (fp->type & SFT_DM) break; if (fp->type & SFT_COUNT) { if ((ERR_ERRWZTRAP == errmsg) || (ERR_ERRWETRAP == errmsg)) { /* Whether ETRAP or ZTRAP we want to rethrow the error at one level down */ SET_ERROR_FRAME(fp); /* reset error_frame to point to the closest counted frame */ assert(fp->flags & SFF_ETRAP_ERR); /* Turn off any device exception related flags now that we are going to handle errors using * $ETRAP or $ZTRAP AT THE PARENT LEVEL only (no more device exceptions). */ dollar_ztrap.str.len = 0; ztrap_explicit_null = FALSE; fp->flags &= SFF_DEV_ACT_ERR_OFF; fp->flags &= SFF_ZTRAP_ERR_OFF; err_act = &dollar_etrap.str; break; } else if (ERR_ERRWIOEXC == errmsg) { /* Error while compiling device exception. Set SFF_ETRAP_ERR bit so control is transferred to * error_return() which in turn will rethrow the error AT THE SAME LEVEL in order to try and * use $ZTRAP or $ETRAP whichever is active. Also set the SFF_DEV_ACT_ERR bit to signify this * is a device exception that is rethrown instead of a ztrap/etrap error. Also assert that * the rethrow will not use IO exception again (thereby ensuring error processing will * eventually terminate instead of indefinitely recursing). */ fp->flags |= (SFF_DEV_ACT_ERR | SFF_ETRAP_ERR); assert(NULL == active_device); /* mdb_condition_handler should have reset it */ break; } else if ((ERR_ERRWZBRK == errmsg) || (ERR_ERRWEXC == errmsg)) { /* For typical exceptions in ZBREAK and ZSTEP, get back to direct mode */ dm_setup(); break; } else { /* The only known way to be here is if the command is a command given in direct mode as * mdb_condition_handler won't drive an error handler in that case which would be caught in * one of the above conditions. Not breaking out of the loop here means the frame will just * unwind and we'll break on the direct mode frame which will be redriven. If the parent frame * is not a direct mode frame, we'll assert in debug or break in pro and just continue. * to direct mode. */ assert(fp->flags && (SFF_INDCE)); if (!fp->old_frame_pointer || !(fp->old_frame_pointer->type & SFT_DM)) { assert(FALSE); break; } } } if (fp->type) { SET_ERR_CODE(fp, errmsg); } /* If this frame is indicated for cache cleanup, do that cleanup * now before we get rid of the pointers used by that cleanup. */ IF_INDR_FRAME_CLEANUP_CACHE_ENTRY_AND_UNMARK(fp); fp->mpc = CODE_ADDRESS(pseudo_ret); fp->ctxt = GTM_CONTEXT(pseudo_ret); fp->flags &= SFF_IMPLTSTART_CALLD_OFF; /* Frame enterable now with mpc reset */ GTMTRIG_ONLY(DBGTRIGR((stderr, "trans_code_cleanup: turning off SFF_IMPLTSTART_CALLD in frame 0x"lvaddr"\n", frame_pointer))); } TREF(transform) = TRUE; if (0 != errmsg) dec_err(VARLSTCNT(1) errmsg); }
void trans_code_cleanup(void) { stack_frame *fp; uint4 err; error_def(ERR_STACKCRIT); error_def(ERR_ERRWZTRAP); error_def(ERR_ERRWETRAP); error_def(ERR_ERRWIOEXC); assert(!(SFT_ZINTR & proc_act_type)); /* With no extra ztrap frame being pushed onto stack, we may miss error(s) * during trans_code if we don't check proc_act_type in addition to * frame_pointer->type below. */ if (SFT_ZTRAP == proc_act_type) { if (0 < dollar_ztrap.str.len) err = (int)ERR_ERRWZTRAP; else { assert(0 < dollar_etrap.str.len); err = (int)ERR_ERRWETRAP; } frame_pointer->flags |= SFF_ZTRAP_ERR; } else if (SFT_DEV_ACT == proc_act_type) { err = ERR_ERRWIOEXC; frame_pointer->flags |= SFF_DEV_ACT_ERR; } else err = 0; proc_act_type = 0; if (compile_time) { compile_time = FALSE; if (stringpool.base != rts_stringpool.base) stringpool = rts_stringpool; } for (fp = frame_pointer; fp; fp = fp->old_frame_pointer) { if (fp->type & SFT_DM) break; if (fp->type & SFT_COUNT) { assert(NULL != err_act); if (!IS_ETRAP) dm_setup(); break; } if (fp->type) { SET_ERR_CODE(fp, err); } /* If this frame is indicated for cache cleanup, do that cleanup now before we get rid of the pointers used by that cleanup. */ IF_INDR_FRAME_CLEANUP_CACHE_ENTRY_AND_UNMARK(fp); fp->mpc = CODE_ADDRESS(pseudo_ret); fp->ctxt = CONTEXT(pseudo_ret); } transform = TRUE; if (err) dec_err(VARLSTCNT(1) err); }
unsigned char *set_zstatus(mstr *src, int arg, unsigned char **ctxtp, boolean_t need_rtsloc) { unsigned char *b_line; /* beginning of line (used to restart line) */ mval val; /* pointer to dollar_zstatus */ unsigned char zstatus_buff[2*OUT_BUFF_SIZE]; unsigned char *zstatus_bptr, *zstatus_iter; int save_arg; size_t util_len ; mval *status_loc; boolean_t trans_frame; DCL_THREADGBL_ACCESS; SETUP_THREADGBL_ACCESS; b_line = 0; if (!need_rtsloc) trans_frame = FALSE; else { /* get the line address of the last "known" MUMPS code that was executed. MUMPS * indirection consitutes MUMPS code that is "unknown" is the sense that there is no * line address for it. */ trans_frame = !(SFT_DM & frame_pointer->type) && ((!(frame_pointer->type & SFT_COUNT || 0 == frame_pointer->type)) || (SFT_ZINTR & frame_pointer->type)); if (trans_frame) { save_arg = arg; SET_ERR_CODE(frame_pointer, arg); } src->len = INTCAST(get_symb_line((unsigned char*)src->addr, &b_line, ctxtp) - (unsigned char*)src->addr); } MV_FORCE_MVAL(&val, arg); n2s(&val); memcpy(zstatus_buff, val.str.addr, val.str.len); zstatus_bptr = zstatus_buff + val.str.len; *zstatus_bptr++ = ','; if (0 != b_line) { memcpy(zstatus_bptr, src->addr, src->len); zstatus_bptr += src->len; *zstatus_bptr++ = ','; } zstatus_iter = zstatus_bptr; util_len = TREF(util_outptr) - TREF(util_outbuff_ptr); if (trans_frame) { /* currently no inserted message (arg) needs arguments. The following code needs * to be changed if any new parametered message is added. */ *(TREF(util_outbuff_ptr)) = '-'; memcpy(&zstatus_buff[OUT_BUFF_SIZE], TREF(util_outbuff_ptr), util_len); /* save original message */ util_out_print(NULL, RESET); /* clear any pending msgs and reset util_out_buff */ gtm_putmsg_noflush(VARLSTCNT(1) arg); memcpy(zstatus_bptr, TREF(util_outbuff_ptr), TREF(util_outptr) - TREF(util_outbuff_ptr)); zstatus_bptr += (TREF(util_outptr) - TREF(util_outbuff_ptr)); *zstatus_bptr++ = ','; memcpy(zstatus_bptr, &zstatus_buff[OUT_BUFF_SIZE], util_len); /* restore original message into util_outbuf */ memcpy(TREF(util_outbuff_ptr), &zstatus_buff[OUT_BUFF_SIZE], util_len); *(TREF(util_outbuff_ptr)) = '%'; TREF(util_outptr) = TREF(util_outbuff_ptr) + util_len; arg = save_arg; } else memcpy(zstatus_bptr, TREF(util_outbuff_ptr), util_len); zstatus_bptr += util_len; for (; zstatus_iter < zstatus_bptr; zstatus_iter++) { if ('\n' == *zstatus_iter) *zstatus_iter = ','; } status_loc = (NULL == zyerr_frame) ? &dollar_zstatus : &dollar_zerror; status_loc->str.len = INTCAST(zstatus_bptr - zstatus_buff); status_loc->str.addr = (char *)zstatus_buff; s2pool(&status_loc->str); status_loc->mvtype = MV_STR; /* If this is a MEMORY issue, setting the ecode is of dubious worth since we are not going * to drive any handlers and it can definitely be expensive in terms of memory use as ecode_add() * (further down the pike) is likely to load the text of the module into storage if it can. So we bypass * ecode setting for these two fatal errors. 02/2008 se */ if (ERR_MEMORY != arg) ecode_set(arg); return (b_line); }