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);
}
Example #2
0
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);
}
Example #3
0
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);
}